Merge remote-tracking branch 'origin/5.12' into 5.13

Change-Id: I71cc71881fb638e207d83a8733bad8f267701c0f
This commit is contained in:
Friedemann Kleint 2019-03-26 08:27:02 +01:00
commit 8f1acd29e4
32 changed files with 363 additions and 96 deletions

View File

@ -465,7 +465,9 @@ defineTest(reloadSpec) {
$$[QT_HOST_DATA/src]/mkspecs/features/mac/toolchain.prf \
$$[QT_HOST_DATA/src]/mkspecs/features/toolchain.prf
_SAVED_CONFIG = $$CONFIG
saved_variables = CONFIG QMAKE_CXXFLAGS
for (name, saved_variables): \
_SAVED_$$name = $$eval($$name)
load(spec_pre)
# qdevice.pri gets written too late (and we can't write it early
# enough, as it's populated in stages, with later ones depending
@ -474,7 +476,8 @@ defineTest(reloadSpec) {
eval($$l)
include($$QMAKESPEC/qmake.conf)
load(spec_post)
CONFIG += $$_SAVED_CONFIG
for (name, saved_variables): \
$$name += $$eval(_SAVED_$$name)
load(default_pre)
# ensure pristine environment for configuration. again.

View File

@ -70,7 +70,7 @@ static QVariant variantFromXml(QXmlStreamReader &xml, Converter::Options options
static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options options)
{
QVariantList list;
while (!xml.atEnd() && !xml.isEndElement()) {
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("list"))) {
xml.readNext();
switch (xml.tokenType()) {
case QXmlStreamReader::StartElement:
@ -107,7 +107,7 @@ static QVariantList listFromXml(QXmlStreamReader &xml, Converter::Options option
static VariantOrderedMap::value_type mapEntryFromXml(QXmlStreamReader &xml, Converter::Options options)
{
QVariant key, value;
while (!xml.atEnd() && !xml.isEndElement()) {
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("entry"))) {
xml.readNext();
switch (xml.tokenType()) {
case QXmlStreamReader::StartElement:
@ -150,7 +150,7 @@ static QVariant mapFromXml(QXmlStreamReader &xml, Converter::Options options)
QVariantMap map1;
VariantOrderedMap map2;
while (!xml.atEnd() && !xml.isEndElement()) {
while (!xml.atEnd() && !(xml.isEndElement() && xml.name() == QLatin1String("map"))) {
xml.readNext();
switch (xml.tokenType()) {
case QXmlStreamReader::StartElement:

View File

@ -374,6 +374,16 @@
]
}
},
"glibc": {
"label": "GNU libc",
"type": "compile",
"test": {
"include": "stdlib.h",
"main": [
"return __GLIBC__;"
]
}
},
"inotify": {
"label": "inotify",
"type": "compile",
@ -593,6 +603,12 @@
"condition": "libs.glib",
"output": [ "privateFeature", "feature" ]
},
"glibc": {
"label": "GNU libc",
"autoDetect": "config.linux",
"condition": "tests.glibc",
"output": [ "privateFeature" ]
},
"iconv": {
"label": "iconv",
"purpose": "Provides internationalization on Unix.",

View File

@ -78,7 +78,11 @@ QT_BEGIN_NAMESPACE
* - statx 4.11 QT_CONFIG(statx)
*/
#if QT_CONFIG(statx)
#if QT_CONFIG(statx) && !QT_CONFIG(glibc)
// if using glibc, the statx() function in sysdeps/unix/sysv/linux/statx.c
// falls back to stat() for us.
// (Using QT_CONFIG(glibc) instead of __GLIBC__ because the macros aren't
// defined in assembler mode)
# define MINLINUX_MAJOR 4
# define MINLINUX_MINOR 11
# define MINLINUX_PATCH 0

View File

@ -2355,6 +2355,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
bool wrap = flags & Qt::MatchWrap;
bool allHits = (hits == -1);
QString text; // only convert to a string if it is needed
const int column = start.column();
QModelIndex p = parent(start);
int from = start.row();
int to = rowCount(p);
@ -2362,7 +2363,7 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
// iterates twice if wrapping
for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
for (int r = from; (r < to) && (allHits || result.count() < hits); ++r) {
QModelIndex idx = index(r, start.column(), p);
QModelIndex idx = index(r, column, p);
if (!idx.isValid())
continue;
QVariant v = data(idx, role);
@ -2401,12 +2402,15 @@ QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
result.append(idx);
}
}
if (recurse && hasChildren(idx)) { // search the hierarchy
result += match(index(0, idx.column(), idx), role,
if (recurse) {
const auto parent = column != 0 ? idx.sibling(idx.row(), 0) : idx;
if (hasChildren(parent)) { // search the hierarchy
result += match(index(0, column, parent), role,
(text.isEmpty() ? value : text),
(allHits ? -1 : hits - result.count()), flags);
}
}
}
// prepare for the next iteration
from = 0;
to = start.row();

View File

@ -61,7 +61,7 @@ public:
/*!
\class QSignalMapper
\inmodule QtCore
\obsolete
\obsolete The recommended solution is connecting the signal to a lambda.
\brief The QSignalMapper class bundles signals from identifiable senders.
\ingroup objectmodel

View File

@ -331,6 +331,7 @@ public:
private:
void init(const QByteArray &ianaId);
QVector<QTimeZonePrivate::Data> getPosixTransitions(qint64 msNear) const;
Data dataForTzTransition(QTzTransitionTime tran) const;
QVector<QTzTransitionTime> m_tranTimes;

View File

@ -943,19 +943,21 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime
return data;
}
QVector<QTimeZonePrivate::Data> QTzTimeZonePrivate::getPosixTransitions(qint64 msNear) const
{
const int year = QDateTime::fromMSecsSinceEpoch(msNear, Qt::UTC).date().year();
// The Data::atMSecsSinceEpoch of the single entry if zone is constant:
qint64 atTime = m_tranTimes.isEmpty() ? msNear : m_tranTimes.last().atMSecsSinceEpoch;
return calculatePosixTransitions(m_posixRule, year - 1, year + 1, atTime);
}
QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const
{
// If we have no rules (so probably an invalid tz), return invalid data:
if (!m_tranTimes.size())
return invalidData();
// If the required time is after the last transition and we have a POSIX rule then use it
if (m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)
&& !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) {
const int year = QDateTime::fromMSecsSinceEpoch(forMSecsSinceEpoch, Qt::UTC).date().year();
QVector<QTimeZonePrivate::Data> posixTrans =
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
m_tranTimes.last().atMSecsSinceEpoch);
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(forMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
return at.atMSecsSinceEpoch <= forMSecsSinceEpoch;
@ -986,13 +988,11 @@ bool QTzTimeZonePrivate::hasTransitions() const
QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch) const
{
// If the required time is after the last transition and we have a POSIX rule then use it
if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)
&& !m_posixRule.isEmpty() && afterMSecsSinceEpoch >= 0) {
const int year = QDateTime::fromMSecsSinceEpoch(afterMSecsSinceEpoch, Qt::UTC).date().year();
QVector<QTimeZonePrivate::Data> posixTrans =
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
m_tranTimes.last().atMSecsSinceEpoch);
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(afterMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch;
@ -1011,19 +1011,19 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince
QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
// If the required time is after the last transition and we have a POSIX rule then use it
if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch
// If the required time is after the last transition (or there were none)
// and we have a POSIX rule then use it:
if ((m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)
&& !m_posixRule.isEmpty() && beforeMSecsSinceEpoch > 0) {
const int year = QDateTime::fromMSecsSinceEpoch(beforeMSecsSinceEpoch, Qt::UTC).date().year();
QVector<QTimeZonePrivate::Data> posixTrans =
calculatePosixTransitions(m_posixRule, year - 1, year + 1,
m_tranTimes.last().atMSecsSinceEpoch);
QVector<QTimeZonePrivate::Data> posixTrans = getPosixTransitions(beforeMSecsSinceEpoch);
auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(),
[beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) {
return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch;
});
Q_ASSERT(it > posixTrans.cbegin());
if (it > posixTrans.cbegin())
return *--it;
// It fell between the last transition (if any) and the first of the POSIX rule:
return m_tranTimes.isEmpty() ? invalidData() : dataForTzTransition(m_tranTimes.last());
}
// Otherwise if we can find a valid tran then use its rule

View File

@ -1552,6 +1552,11 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
if (image.isNull())
return QPixmap();
if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
qWarning("QPixmap::fromImage: QPixmap cannot be created without a QGuiApplication");
return QPixmap();
}
QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImage(image, flags);
return QPixmap(data.take());
@ -1574,6 +1579,11 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags)
if (image.isNull())
return QPixmap();
if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
qWarning("QPixmap::fromImageInPlace: QPixmap cannot be created without a QGuiApplication");
return QPixmap();
}
QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageInPlace(image, flags);
return QPixmap(data.take());
@ -1593,6 +1603,11 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags)
*/
QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags)
{
if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(QCoreApplication::instance()))) {
qWarning("QPixmap::fromImageReader: QPixmap cannot be created without a QGuiApplication");
return QPixmap();
}
QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageReader(imageReader, flags);
return QPixmap(data.take());

View File

@ -708,10 +708,11 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w,
const QScreen *screen = effectiveScreen(w);
if (!screen)
return initialGeometry;
const auto *wp = qt_window_private(const_cast<QWindow*>(w));
QRect rect(QHighDpi::fromNativePixels(initialGeometry, w));
if (wp->resizeAutomatic)
rect.setSize(fixInitialSize(rect.size(), w, defaultWidth, defaultHeight));
if (qt_window_private(const_cast<QWindow*>(w))->positionAutomatic
&& w->type() != Qt::Popup) {
if (wp->positionAutomatic && w->type() != Qt::Popup) {
const QRect availableGeometry = screen->availableGeometry();
// Center unless the geometry ( + unknown window frame) is too large for the screen).
if (rect.height() < (availableGeometry.height() * 8) / 9

View File

@ -90,6 +90,7 @@ public:
, receivedExpose(false)
, positionPolicy(WindowFrameExclusive)
, positionAutomatic(true)
, resizeAutomatic(true)
, contentOrientation(Qt::PrimaryOrientation)
, opacity(qreal(1.0))
, minimumSize(0, 0)
@ -156,6 +157,8 @@ public:
virtual void processSafeAreaMarginsChanged() {};
bool isPopup() const { return (windowFlags & Qt::WindowType_Mask) == Qt::Popup; }
void setAutomaticPositionAndResizeEnabled(bool a)
{ positionAutomatic = resizeAutomatic = a; }
static QWindowPrivate *get(QWindow *window) { return window->d_func(); }
@ -179,6 +182,11 @@ public:
bool receivedExpose;
PositionPolicy positionPolicy;
bool positionAutomatic;
// resizeAutomatic suppresses resizing by QPlatformWindow::initialGeometry().
// It also indicates that width/height=0 is acceptable (for example, for
// the QRollEffect widget) and is thus not cleared in setGeometry().
// An alternative approach might be using -1,-1 as a default size.
bool resizeAutomatic;
Qt::ScreenOrientation contentOrientation;
qreal opacity;
QRegion mask;

View File

@ -1754,7 +1754,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
#ifdef Q_OS_DARWIN
if (actualFontEngine->type() == QFontEngine::Mac) {
if (actualFontEngine->fontDef.stretch != 100) {
if (actualFontEngine->fontDef.stretch != 100 && actualFontEngine->fontDef.stretch != QFont::AnyStretch) {
QFixed stretch = QFixed(int(actualFontEngine->fontDef.stretch)) / QFixed(100);
for (uint i = 0; i < num_glyphs; ++i)
g.advances[i] *= stretch;

View File

@ -191,8 +191,8 @@ bool QNetworkCacheMetaData::isValid() const
Some cache implementations can keep these cache items in memory for performance reasons,
but for security reasons they should not be written to disk.
Specifically with http, documents marked with Pragma: no-cache, or have a Cache-control set to
no-store or no-cache or any https document that doesn't have "Cache-control: public" set will
Specifically with http, documents with Cache-control set to no-store or any
https document that doesn't have "Cache-control: public" set will
set the saveToDisk to false.
\sa setSaveToDisk()

View File

@ -87,15 +87,16 @@ bool QNetworkAccessCacheBackend::sendCacheContents()
setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute));
// set the raw headers
QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders();
QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(),
end = rawHeaders.constEnd();
for ( ; it != end; ++it) {
if (it->first.toLower() == "cache-control" &&
it->second.toLower().contains("must-revalidate")) {
const QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders();
for (const auto &header : rawHeaders) {
if (header.first.toLower() == "cache-control") {
const QByteArray cacheControlValue = header.second.toLower();
if (cacheControlValue.contains("must-revalidate")
|| cacheControlValue.contains("no-cache")) {
return false;
}
setRawHeader(it->first, it->second);
}
setRawHeader(header.first, header.second);
}
// handle a possible redirect

View File

@ -524,6 +524,8 @@ bool QNetworkReplyHttpImplPrivate::loadFromCacheIfAllowed(QHttpNetworkRequest &h
QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second);
if (cacheControl.contains("must-revalidate"))
return false;
if (cacheControl.contains("no-cache"))
return false;
}
QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
@ -1731,18 +1733,8 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe
if (httpRequest.operation() == QHttpNetworkRequest::Get) {
canDiskCache = true;
// 14.32
// HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client
// had sent "Cache-Control: no-cache".
it = cacheHeaders.findRawHeader("pragma");
if (it != cacheHeaders.rawHeaders.constEnd()
&& it->second == "no-cache")
canDiskCache = false;
// HTTP/1.1. Check the Cache-Control header
if (cacheControl.contains("no-cache"))
canDiskCache = false;
else if (cacheControl.contains("no-store"))
if (cacheControl.contains("no-store"))
canDiskCache = false;
// responses to POST might be cacheable

View File

@ -250,6 +250,9 @@ void QCocoaMenu::syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUp
if (wasMerged) {
oldItem.enabled = NO;
oldItem.hidden = YES;
oldItem.keyEquivalent = @"";
oldItem.keyEquivalentModifierMask = NSEventModifierFlagCommand;
} else {
[m_nativeMenu removeItem:oldItem];
}

View File

@ -158,10 +158,13 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
pal.setColor(QPalette::Active, QPalette::ButtonText, qc);
pal.setColor(QPalette::Inactive, QPalette::ButtonText, qc);
qc = qt_mac_toQColor(mac_widget_colors[i].inactive);
pal.setColor(QPalette::Disabled, QPalette::Text, qc);
pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
pal.setColor(QPalette::Disabled, QPalette::ButtonText, qc);
}
if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette
|| mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) {

View File

@ -1132,7 +1132,8 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
// TODO: No concept of WA_wasMoved yet that would indicate a
// CW_USEDEFAULT unless set. For now, assume that 0,0 means 'default'
// for toplevels.
if (geometry.isValid()) {
if (geometry.isValid()
|| !qt_window_private(const_cast<QWindow *>(w))->resizeAutomatic) {
frameX = geometry.x();
frameY = geometry.y();
const QMargins effectiveMargins = margins + customMargins;

View File

@ -2645,6 +2645,13 @@ bool QXRenderGlyphCache::addGlyphs(const QTextItemInt &ti,
if (glyph == 0 || glyph->format != glyphFormat())
return false;
if (glyph->format == QFontEngine::Format_Mono) {
// Must convert bitmap from msb to lsb bit order
QImage img(glyph->data, glyph->width, glyph->height, QImage::Format_Mono);
img = img.convertToFormat(QImage::Format_MonoLSB);
memcpy(glyph->data, img.constBits(), static_cast<size_t>(img.sizeInBytes()));
}
set->setGlyph(glyphs[i], spp, glyph);
Q_ASSERT(glyph->data || glyph->width == 0 || glyph->height == 0);

View File

@ -356,15 +356,44 @@ static const qreal titleBarButtonSpacing = 8;
// active: window is active
// selected: tab is selected
// hovered: tab is hovered
static const QColor tabBarTabBackgroundActive(190, 190, 190);
static const QColor tabBarTabBackgroundActiveHovered(178, 178, 178);
static const QColor tabBarTabBackgroundActiveSelected(211, 211, 211);
static const QColor tabBarTabBackground(227, 227, 227);
static const QColor tabBarTabBackgroundSelected(246, 246, 246);
static const QColor tabBarTabLineActive(160, 160, 160);
static const QColor tabBarTabLineActiveHovered(150, 150, 150);
static const QColor tabBarTabLine(210, 210, 210);
static const QColor tabBarTabLineSelected(189, 189, 189);
bool isDarkMode() { return qt_mac_applicationIsInDarkMode(); }
static const QColor lightTabBarTabBackgroundActive(190, 190, 190);
static const QColor darkTabBarTabBackgroundActive(38, 38, 38);
static const QColor tabBarTabBackgroundActive() { return isDarkMode() ? darkTabBarTabBackgroundActive : lightTabBarTabBackgroundActive; }
static const QColor lightTabBarTabBackgroundActiveHovered(178, 178, 178);
static const QColor darkTabBarTabBackgroundActiveHovered(32, 32, 32);
static const QColor tabBarTabBackgroundActiveHovered() { return isDarkMode() ? darkTabBarTabBackgroundActiveHovered : lightTabBarTabBackgroundActiveHovered; }
static const QColor lightTabBarTabBackgroundActiveSelected(211, 211, 211);
static const QColor darkTabBarTabBackgroundActiveSelected(52, 52, 52);
static const QColor tabBarTabBackgroundActiveSelected() { return isDarkMode() ? darkTabBarTabBackgroundActiveSelected : lightTabBarTabBackgroundActiveSelected; }
static const QColor lightTabBarTabBackground(227, 227, 227);
static const QColor darkTabBarTabBackground(38, 38, 38);
static const QColor tabBarTabBackground() { return isDarkMode() ? darkTabBarTabBackground : lightTabBarTabBackground; }
static const QColor lightTabBarTabBackgroundSelected(246, 246, 246);
static const QColor darkTabBarTabBackgroundSelected(52, 52, 52);
static const QColor tabBarTabBackgroundSelected() { return isDarkMode() ? darkTabBarTabBackgroundSelected : lightTabBarTabBackgroundSelected; }
static const QColor lightTabBarTabLineActive(160, 160, 160);
static const QColor darkTabBarTabLineActive(90, 90, 90);
static const QColor tabBarTabLineActive() { return isDarkMode() ? darkTabBarTabLineActive : lightTabBarTabLineActive; }
static const QColor lightTabBarTabLineActiveHovered(150, 150, 150);
static const QColor darkTabBarTabLineActiveHovered(90, 90, 90);
static const QColor tabBarTabLineActiveHovered() { return isDarkMode() ? darkTabBarTabLineActiveHovered : lightTabBarTabLineActiveHovered; }
static const QColor lightTabBarTabLine(210, 210, 210);
static const QColor darkTabBarTabLine(90, 90, 90);
static const QColor tabBarTabLine() { return isDarkMode() ? darkTabBarTabLine : lightTabBarTabLine; }
static const QColor lightTabBarTabLineSelected(189, 189, 189);
static const QColor darkTabBarTabLineSelected(90, 90, 90);
static const QColor tabBarTabLineSelected() { return isDarkMode() ? darkTabBarTabLineSelected : lightTabBarTabLineSelected; }
static const QColor tabBarCloseButtonBackgroundHovered(162, 162, 162);
static const QColor tabBarCloseButtonBackgroundPressed(153, 153, 153);
static const QColor tabBarCloseButtonBackgroundSelectedHovered(192, 192, 192);
@ -561,7 +590,7 @@ void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, in
const bool active = (tabOpt->state & QStyle::State_Active);
const bool selected = (tabOpt->state & QStyle::State_Selected);
const QRect bodyRect(1, 1, width - 2, height - 2);
const QRect bodyRect(1, 2, width - 2, height - 3);
const QRect topLineRect(1, 0, width - 2, 1);
const QRect bottomLineRect(1, height - 1, width - 2, 1);
if (selected) {
@ -572,27 +601,27 @@ void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, in
p->fillRect(tabRect, QColor(Qt::transparent));
p->restore();
} else if (active) {
p->fillRect(bodyRect, tabBarTabBackgroundActiveSelected);
p->fillRect(bodyRect, tabBarTabBackgroundActiveSelected());
// top line
p->fillRect(topLineRect, tabBarTabLineSelected);
p->fillRect(topLineRect, tabBarTabLineSelected());
} else {
p->fillRect(bodyRect, tabBarTabBackgroundSelected);
p->fillRect(bodyRect, tabBarTabBackgroundSelected());
}
} else {
// when the mouse is over non selected tabs they get a new color
const bool hover = (tabOpt->state & QStyle::State_MouseOver);
if (hover) {
// fill body
p->fillRect(bodyRect, tabBarTabBackgroundActiveHovered);
p->fillRect(bodyRect, tabBarTabBackgroundActiveHovered());
// bottom line
p->fillRect(bottomLineRect, tabBarTabLineActiveHovered);
p->fillRect(bottomLineRect, isDarkMode() ? QColor(Qt::black) : tabBarTabLineActiveHovered());
}
}
// separator lines between tabs
const QRect leftLineRect(0, 1, 1, height - 2);
const QRect rightLineRect(width - 1, 1, 1, height - 2);
const QColor separatorLineColor = active ? tabBarTabLineActive : tabBarTabLine;
const QColor separatorLineColor = active ? tabBarTabLineActive() : tabBarTabLine();
p->fillRect(leftLineRect, separatorLineColor);
p->fillRect(rightLineRect, separatorLineColor);
}
@ -612,17 +641,20 @@ void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *
// fill body
const QRect bodyRect(0, 1, width, height - 1);
const QColor bodyColor = active ? tabBarTabBackgroundActive : tabBarTabBackground;
const QColor bodyColor = active ? tabBarTabBackgroundActive() : tabBarTabBackground();
p->fillRect(bodyRect, bodyColor);
// top line
const QRect topLineRect(0, 0, width, 1);
const QColor topLineColor = active ? tabBarTabLineActive : tabBarTabLine;
const QColor topLineColor = active ? tabBarTabLineActive() : tabBarTabLine();
p->fillRect(topLineRect, topLineColor);
// bottom line
const QRect bottomLineRect(0, height - 1, width, 1);
const QColor bottomLineColor = active ? tabBarTabLineActive : tabBarTabLine;
bool isDocument = false;
if (const QTabBar *tabBar = qobject_cast<const QTabBar*>(w))
isDocument = tabBar->documentMode();
const QColor bottomLineColor = isDocument && isDarkMode() ? QColor(Qt::black) : active ? tabBarTabLineActive() : tabBarTabLine();
p->fillRect(bottomLineRect, bottomLineColor);
}
#endif
@ -1227,11 +1259,17 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
Q_UNREACHABLE();
}
const auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor);
auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor);
if (!qt_mac_applicationIsInDarkMode()) {
// This color already has alpha ~ 0.25, this value is too small - the ring is
// very pale and nothing like the native one. 0.39 makes it better (not ideal
// anyway). The color seems to be correct in dark more without any modification.
focusRingColor.setAlphaF(0.39);
}
p->save();
p->setRenderHint(QPainter::Antialiasing);
p->setOpacity(0.5);
if (cw.type == SegmentedControl_First) {
// TODO Flip left-right
}
@ -3536,7 +3574,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (tbstyle == Qt::ToolButtonTextOnly
|| (tbstyle != Qt::ToolButtonTextOnly && !down)) {
QPen pen = p->pen();
QColor light = down ? Qt::black : Qt::white;
QColor light = down || isDarkMode() ? Qt::black : Qt::white;
light.setAlphaF(0.375f);
p->setPen(light);
p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text);
@ -3958,6 +3996,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (!tabBar->tabTextColor(tabBar->currentIndex()).isValid())
myTab.palette.setColor(QPalette::WindowText, Qt::white);
if (myTab.documentMode && isDarkMode()) {
bool active = (myTab.state & State_Selected) && (myTab.state & State_Active);
myTab.palette.setColor(QPalette::WindowText, active ? Qt::white : Qt::gray);
}
int heightOffset = 0;
if (verticalTabs) {
heightOffset = -1;
@ -4444,16 +4487,17 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
p->fillRect(opt->rect, linearGrad);
p->save();
QRect toolbarRect = isDarkMode ? opt->rect.adjusted(0, 0, 0, 1) : opt->rect;
if (opt->state & State_Horizontal) {
p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
p->drawLine(toolbarRect.topLeft(), toolbarRect.topRight());
p->setPen(isDarkMode ? darkModeSeparatorLine :mainWindowGradientEnd.darker(114));
p->drawLine(opt->rect.bottomLeft(), opt->rect.bottomRight());
p->drawLine(toolbarRect.bottomLeft(), toolbarRect.bottomRight());
} else {
p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
p->drawLine(toolbarRect.topLeft(), toolbarRect.bottomLeft());
p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientEnd.darker(114));
p->drawLine(opt->rect.topRight(), opt->rect.bottomRight());
p->drawLine(toolbarRect.topRight(), toolbarRect.bottomRight());
}
p->restore();

View File

@ -1543,14 +1543,19 @@ void QWidgetPrivate::createTLSysExtra()
extra->topextra->window->setMaximumSize(QSize(extra->maxw, extra->maxh));
if (extra->topextra->opacity != 255 && q->isWindow())
extra->topextra->window->setOpacity(qreal(extra->topextra->opacity) / qreal(255));
const bool isTipLabel = q->inherits("QTipLabel");
const bool isAlphaWidget = !isTipLabel && q->inherits("QAlphaWidget");
#ifdef Q_OS_WIN
// Pass on native parent handle for Widget embedded into Active X.
const QVariant activeXNativeParentHandle = q->property(activeXNativeParentHandleProperty);
if (activeXNativeParentHandle.isValid())
extra->topextra->window->setProperty(activeXNativeParentHandleProperty, activeXNativeParentHandle);
if (q->inherits("QTipLabel") || q->inherits("QAlphaWidget"))
if (isTipLabel || isAlphaWidget)
extra->topextra->window->setProperty("_q_windowsDropShadow", QVariant(true));
#endif
if (isTipLabel || isAlphaWidget || q->inherits("QRollEffect"))
qt_window_private(extra->topextra->window)->setAutomaticPositionAndResizeEnabled(false);
}
}

View File

@ -32,10 +32,13 @@
#include <QStandardItemModel>
#include <QStringListModel>
#include <QTest>
#include <QLoggingCategory>
#include "dynamictreemodel.h"
#include "qidentityproxymodel.h"
Q_LOGGING_CATEGORY(lcItemModels, "qt.corelib.tests.itemmodels")
class DataChangedModel : public QAbstractListModel
{
public:
@ -390,7 +393,7 @@ void dump(QAbstractItemModel* model, QString const& indent = " - ", QModelIndex
for (auto row = 0; row < model->rowCount(parent); ++row)
{
auto idx = model->index(row, 0, parent);
qDebug() << (indent + idx.data().toString());
qCDebug(lcItemModels) << (indent + idx.data().toString());
dump(model, indent + "- ", idx);
}
}

View File

@ -125,6 +125,7 @@ private:
tst_QItemModel::tst_QItemModel()
{
qRegisterMetaType<QAbstractItemModel::LayoutChangeHint>();
qRegisterMetaType<QList<QPersistentModelIndex>>();
}
void tst_QItemModel::init()
@ -181,7 +182,7 @@ void tst_QItemModel::nonDestructiveBasicTest()
currentModel->hasChildren(QModelIndex());
currentModel->hasIndex(0, 0);
currentModel->headerData(0, Qt::Horizontal);
currentModel->index(0,0), QModelIndex();
currentModel->index(0,0);
currentModel->itemData(QModelIndex());
QVariant cache;
currentModel->match(QModelIndex(), -1, cache);

View File

@ -38,6 +38,8 @@
#include <qdebug.h>
Q_LOGGING_CATEGORY(lcItemModels, "qt.corelib.tests.itemmodels")
// Testing get/set functions
void tst_QSortFilterProxyModel::getSetCheck()
{
@ -2361,6 +2363,45 @@ void tst_QSortFilterProxyModel::match()
QCOMPARE(indexes.at(i).row(), expectedProxyItems.at(i));
}
QList<QStandardItem *> createStandardItemList(const QString &prefix, int n)
{
QList<QStandardItem *> result;
for (int i = 0; i < n; ++i)
result.append(new QStandardItem(prefix + QString::number(i)));
return result;
}
// QTBUG-73864, recursive search in a tree model.
void tst_QSortFilterProxyModel::matchTree()
{
QStandardItemModel model(0, 2);
// Header00 Header01
// Header10 Header11
// Item00 Item01
// Item10 Item11
model.appendRow(createStandardItemList(QLatin1String("Header0"), 2));
auto headerRow = createStandardItemList(QLatin1String("Header1"), 2);
model.appendRow(headerRow);
headerRow.first()->appendRow(createStandardItemList(QLatin1String("Item0"), 2));
headerRow.first()->appendRow(createStandardItemList(QLatin1String("Item1"), 2));
auto item11 = model.match(model.index(1, 1), Qt::DisplayRole, QLatin1String("Item11"), 20,
Qt::MatchRecursive).value(0);
QVERIFY(item11.isValid());
QCOMPARE(item11.data().toString(), QLatin1String("Item11"));
// Repeat in proxy model
QSortFilterProxyModel proxy;
proxy.setSourceModel(&model);
auto proxyItem11 = proxy.match(proxy.index(1, 1), Qt::DisplayRole, QLatin1String("Item11"), 20,
Qt::MatchRecursive).value(0);
QVERIFY(proxyItem11.isValid());
QCOMPARE(proxyItem11.data().toString(), QLatin1String("Item11"));
QCOMPARE(proxy.mapToSource(proxyItem11).internalId(), item11.internalId());
}
void tst_QSortFilterProxyModel::insertIntoChildrenlessItem()
{
QStandardItemModel model;
@ -4277,7 +4318,7 @@ public:
QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override
{
// QTBUG-44962: Would we always expect the parent to belong to the model
qDebug() << parent.model() << this;
qCDebug(lcItemModels) << parent.model() << this;
Q_ASSERT(!parent.isValid() || parent.model() == this);
quintptr parentId = (parent.isValid()) ? parent.internalId() : 0;
@ -4363,7 +4404,7 @@ void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes()
// The use of qDebug here makes sufficient use of the heap to
// cause corruption at runtime with normal use on linux (before
// the fix). valgrind confirms the fix.
qDebug() << persistentIndex.parent();
qCDebug(lcItemModels) << persistentIndex.parent();
QVERIFY(persistentIndex.parent().isValid());
}

View File

@ -109,6 +109,7 @@ private slots:
void selectionFilteredOut();
void match_data();
void match();
void matchTree();
void insertIntoChildrenlessItem();
void invalidateMappedChildren();
void insertRowIntoFilteredParent();
@ -186,4 +187,6 @@ private:
Q_DECLARE_METATYPE(QAbstractItemModel::LayoutChangeHint)
Q_DECLARE_LOGGING_CATEGORY(lcItemModels)
#endif // TST_QSORTFILTERPROXYMODEL_H

View File

@ -0,0 +1,4 @@
CONFIG += testcase
TARGET = tst_qdatastream_core_pixmap
QT += testlib
SOURCES = tst_qdatastream_core_pixmap.cpp

View File

@ -0,0 +1,68 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QtGui/QBitmap>
#include <QtGui/QPalette>
#include <QtGui/QPixmap>
#include <QtGui/QPicture>
#include <QtGui/QTextLength>
#include <QtGui/QPainter>
#include <QtGui/QPen>
class tst_QDataStream : public QObject
{
Q_OBJECT
private slots:
void stream_with_pixmap();
};
void tst_QDataStream::stream_with_pixmap()
{
// This is a QVariantMap with a 3x3 red QPixmap and two strings inside
const QByteArray ba = QByteArray::fromBase64("AAAAAwAAAAIAegAAAAoAAAAACgB0AGgAZQByAGUAAAACAHAAAABBAAAAAAGJUE5HDQoaCgAAAA1JSERSAAAAAwAAAAMIAgAAANlKIugAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAQSURBVAiZY/zPAAVMDJgsAB1bAQXZn5ieAAAAAElFTkSuQmCCAAAAAgBhAAAACgAAAAAKAGgAZQBsAGwAbw==");
QImage dummy; // Needed to make sure qtGui is loaded
QTest::ignoreMessage(QtWarningMsg, "QPixmap::fromImageInPlace: QPixmap cannot be created without a QGuiApplication");
QVariantMap map;
QDataStream d(ba);
d.setVersion(QDataStream::Qt_5_12);
d >> map;
QCOMPARE(map["a"].toString(), QString("hello"));
QCOMPARE(map["p"].value<QPixmap>(), QPixmap()); // the pixmap is null because this is not a QGuiApplication
QCOMPARE(map["z"].toString(), QString("there"));
}
QTEST_GUILESS_MAIN(tst_QDataStream)
#include "tst_qdatastream_core_pixmap.moc"

View File

@ -6,6 +6,7 @@ SUBDIRS = \
qcborvalue \
qcborvalue_json \
qdatastream \
qdatastream_core_pixmap \
qtextstream \
qxmlstream

View File

@ -539,6 +539,8 @@ void tst_QTimeZone::checkOffset_data()
int year, month, day, hour, min, sec;
int std, dst;
} table[] = {
// Zone with no transitions (QTBUG-74614, when TZ backend uses minimalist data)
{ "Etc/UTC", "epoch", 1970, 1, 1, 0, 0, 0, 0, 0 },
// Kiev: regression test for QTBUG-64122 (on MS):
{ "Europe/Kiev", "summer", 2017, 10, 27, 12, 0, 0, 2 * 3600, 3600 },
{ "Europe/Kiev", "winter", 2017, 10, 29, 12, 0, 0, 2 * 3600, 0 }
@ -551,6 +553,8 @@ void tst_QTimeZone::checkOffset_data()
<< QDateTime(QDate(entry.year, entry.month, entry.day),
QTime(entry.hour, entry.min, entry.sec), zone)
<< entry.dst + entry.std << entry.std << entry.dst;
} else {
qWarning("Skipping %s@%s test as zone is invalid", entry.zone, entry.nick);
}
}
}

View File

@ -251,9 +251,14 @@ void tst_QAbstractNetworkCache::cacheControl_data()
QTest::newRow("200-1") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol-expire.cgi" << false;
QTest::newRow("200-2") << QNetworkRequest::AlwaysNetwork << "httpcachetest_cachecontrol.cgi?no-cache" << AlwaysFalse;
QTest::newRow("200-3") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?no-cache" << false;
QTest::newRow("200-3") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?no-cache" << true;
QTest::newRow("200-4") << QNetworkRequest::AlwaysCache << "httpcachetest_cachecontrol.cgi?no-cache" << false;
QTest::newRow("200-5") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol.cgi?no-cache" << false;
QTest::newRow("200-5") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol.cgi?no-cache" << true;
QTest::newRow("200-6") << QNetworkRequest::AlwaysNetwork << "httpcachetest_cachecontrol.cgi?no-store" << AlwaysFalse;
QTest::newRow("200-7") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?no-store" << false;
QTest::newRow("200-8") << QNetworkRequest::AlwaysCache << "httpcachetest_cachecontrol.cgi?no-store" << false;
QTest::newRow("200-9") << QNetworkRequest::PreferCache << "httpcachetest_cachecontrol.cgi?no-store" << false;
QTest::newRow("304-0") << QNetworkRequest::PreferNetwork << "httpcachetest_cachecontrol.cgi?max-age=1000" << true;

View File

@ -3976,7 +3976,7 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data()
"HTTP/1.0 200\r\n"
"Connection: keep-alive\r\n"
"Content-Type: text/plain\r\n"
"Cache-control: no-cache\r\n"
"Cache-control: no-store\r\n"
"Content-length: 8\r\n"
"\r\n"
"Reloaded";
@ -4002,6 +4002,33 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data()
content.second = "Not-reloaded";
content.first.setLastModified(past);
// "no-cache"
rawHeaders.clear();
rawHeaders << QNetworkCacheMetaData::RawHeader("Date", QLocale::c().toString(past, dateFormat).toLatin1())
<< QNetworkCacheMetaData::RawHeader("Cache-control", "no-cache");
content.first.setRawHeaders(rawHeaders);
content.first.setLastModified(past);
content.first.setExpirationDate(future);
// "no-cache" does not mean "no cache", just that we must consult remote first
QTest::newRow("no-cache,200,always-network")
<< reply200 << "Reloaded" << content << int(QNetworkRequest::AlwaysNetwork) << QStringList() << false << true;
QTest::newRow("no-cache,200,prefer-network")
<< reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << false << true;
QTest::newRow("no-cache,200,prefer-cache")
<< reply200 << "Reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << false << true;
// We're not allowed by the spec to deliver cached data without checking if it is still
// up-to-date.
QTest::newRow("no-cache,200,always-cache")
<< reply200 << QString() << content << int(QNetworkRequest::AlwaysCache) << QStringList() << false << false;
QTest::newRow("no-cache,304,prefer-network")
<< reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << true << true;
QTest::newRow("no-cache,304,prefer-cache")
<< reply304 << "Not-reloaded" << content << int(QNetworkRequest::PreferCache) << QStringList() << true << true;
QTest::newRow("no-cache,304,always-cache")
<< reply304 << QString() << content << int(QNetworkRequest::AlwaysCache) << QStringList() << false << false;
//
// Set to expired
//

View File

@ -1343,8 +1343,10 @@ void tst_QMainWindow::restoreState()
{
QMainWindow mw;
QToolBar tb(&mw);
tb.setObjectName(QLatin1String("toolBar"));
mw.addToolBar(Qt::TopToolBarArea, &tb);
QDockWidget dw(&mw);
dw.setObjectName(QLatin1String("dock"));
mw.addDockWidget(Qt::LeftDockWidgetArea, &dw);
QByteArray state;