Merge 5.6 into 5.6.2

Change-Id: I58b06ecd9c7d80f38ed4ebb36bde9e7c09486a20
bb10
Oswald Buddenhagen 2016-08-31 11:36:13 +02:00
commit 8d8c7b31ba
54 changed files with 685 additions and 582 deletions

View File

@ -17,6 +17,7 @@ CFLAGS="$SYSROOT_FLAG"
CXXFLAGS="$SYSROOT_FLAG"
MAC_ARCH_CXXFLAGS=""
MAC_ARCH_LFLAGS=""
QMAKE_ARGS=
while [ "$#" -gt 0 ]; do
PARAM=$1
case $PARAM in
@ -56,7 +57,9 @@ while [ "$#" -gt 0 ]; do
CXXFLAGS="$CXXFLAGS $PARAM \"$2\""
shift
;;
*) ;;
*)
QMAKE_ARGS="$QMAKE_ARGS $PARAM"
;;
esac
shift
done
@ -83,6 +86,7 @@ set -- \
"QMAKE_CFLAGS+=$MAC_ARCH_CFLAGS" \
"QMAKE_CXXFLAGS*=$CXXFLAGS" \
"QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" \
$QMAKE_ARGS \
"$SRCDIR/$TEST/$EXE.pro" \
-o "$OUTDIR/$TEST/Makefile"
if [ "$VERBOSE" = "yes" ]; then

11
configure vendored
View File

@ -4293,8 +4293,12 @@ compileTest()
if [ "$CFG_SHARED" = "no" ]; then
test_config="$QMAKE_CONFIG static"
fi
TEST_CONFIG_FLAGS=
if [ -z "$PKG_CONFIG" ]; then
TEST_CONFIG_FLAGS="QT_CONFIG+=no-pkg-config"
fi
echo $ECHO_N "checking for $name... $ECHO_C"
"$unixtests/compile.test" "$XQMAKESPEC" "$test_config" $OPT_VERBOSE "$relpath" "$outpath" "$path" "$name" $I_FLAGS $D_FLAGS $L_FLAGS "$@"
"$unixtests/compile.test" "$XQMAKESPEC" "$test_config" $OPT_VERBOSE "$relpath" "$outpath" "$path" "$name" $I_FLAGS $D_FLAGS $L_FLAGS $TEST_CONFIG_FLAGS "$@"
}
compileTestWithPkgConfig()
@ -4781,8 +4785,9 @@ for _SQLDR in $CFG_SQL_AVAILABLE; do
[ -z "$CFG_MYSQL_CONFIG" ] && CFG_MYSQL_CONFIG=`"$WHICH" mysql_config`
if [ -x "$CFG_MYSQL_CONFIG" ]; then
QT_CFLAGS_MYSQL=`$CFG_MYSQL_CONFIG --include 2>/dev/null | filterIncludeOptions`
QT_LFLAGS_MYSQL_R=`$CFG_MYSQL_CONFIG --libs_r 2>/dev/null | filterLibraryOptions`
QT_LFLAGS_MYSQL=`$CFG_MYSQL_CONFIG --libs 2>/dev/null | filterLibraryOptions`
# -rdynamic should not be returned by mysql_config, but is on RHEL 6.6
QT_LFLAGS_MYSQL_R=`$CFG_MYSQL_CONFIG --libs_r 2>/dev/null | filterLibraryOptions | sed "s/-rdynamic//"`
QT_LFLAGS_MYSQL=`$CFG_MYSQL_CONFIG --libs 2>/dev/null | filterLibraryOptions | sed "s/-rdynamic//"`
QT_MYSQL_VERSION=`$CFG_MYSQL_CONFIG --version 2>/dev/null`
QT_MYSQL_VERSION_MAJOR=`echo $QT_MYSQL_VERSION | cut -d . -f 1`
fi

View File

@ -22,7 +22,9 @@
</Properties>
<Dependencies>
<TargetDeviceFamily Name=\"Windows.Universal\" MinVersion=\"10.0.10586.0\" MaxVersionTested=\"10.0.10586.0\" />$${WINRT_MANIFEST.dependencies}
<TargetDeviceFamily Name=\"Windows.Universal\"
MinVersion=\"$${WINRT_MANIFEST.minVersion}\"
MaxVersionTested=\"$${WINRT_MANIFEST.maxVersionTested}\" />$${WINRT_MANIFEST.dependencies}
</Dependencies>
<Resources>

View File

@ -13,7 +13,7 @@ equals(TEMPLATE, subdirs): return()
# It's likely that these extra flags will be wrong for host builds,
# and the bootstrapped tools usually don't need them anyway.
host_build:force_bootstrap: return()
host_build:cross_compile: return()
# The headersclean check needs defines and includes even for
# header-only modules.

View File

@ -44,9 +44,9 @@ contains(TEMPLATE, .*lib) {
QMAKE_PRL_INSTALL_REPLACE += lib_replace
}
# The remainder of this file must not apply to bootstrapped tools,
# The remainder of this file must not apply to host tools/libraries,
# as the host compiler's version and capabilities are not checked.
host_build:force_bootstrap: return()
host_build:cross_compile: return()
warnings_are_errors:warning_clean {
# If the module declares that it has does its clean-up of warnings, enable -Werror.
@ -54,10 +54,10 @@ warnings_are_errors:warning_clean {
# compiler.
clang:!ios {
# Apple clang 4.0-4.2,5.0-5.1,6.0-6.4
# Regular clang 3.3-3.8
# Regular clang 3.3-3.9
apple_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
reg_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]")|contains(reg_ver, "3\\.[3-8]") {
contains(apple_ver, "4\\.[012]|5\\.[01]|6\\.[01234]")|contains(reg_ver, "3\\.[3-9]") {
QMAKE_CXXFLAGS_WARN_ON += -Werror -Wno-error=\\$${LITERAL_HASH}warnings -Wno-error=deprecated-declarations $$WERROR
}
} else:intel_icc:linux {

View File

@ -31,6 +31,8 @@
# WINRT_MANIFEST.capabilities: Specifies capabilities to add to the capability list.
# WINRT_MANIFEST.capabilities_device: Specifies device capabilities to add to the capability list. (location, webcam...)
# WINRT_MANIFEST.dependencies: Specifies dependencies required by the package.
# WINRT_MANIFEST.minVersion: Specifies the minimum required Windows version to run the package. Defaults to %UCRTVersion%
# WINRT_MANIFEST.maxVersionTested: Specifies the maximum Windows version the package has been tested against. Defaults to WINRT_MANIFEST.minVersion
# The manifest is generated for each build pass for normal apps, and only once for vcapps.
# - Normal apps have their package root directory in the same place as the target (one for each build pass).
@ -91,6 +93,11 @@
isEmpty(WINRT_MANIFEST.background): WINRT_MANIFEST.background = green
isEmpty(WINRT_MANIFEST.foreground): WINRT_MANIFEST.foreground = light
isEmpty(WINRT_MANIFEST.default_language): WINRT_MANIFEST.default_language = en
*-msvc2015 {
isEmpty(WINRT_MANIFEST.minVersion): WINRT_MANIFEST.minVersion = $$(UCRTVersion)
isEmpty(WINRT_MANIFEST.minVersion): error("No UCRTVersion found in environment."))
isEmpty(WINRT_MANIFEST.maxVersionTested): WINRT_MANIFEST.maxVersionTested = $$WINRT_MANIFEST.minVersion
}
INDENT = "$$escape_expand(\\r\\n) "

View File

@ -33,7 +33,8 @@
##
#############################################################################
booted_simulator=$(xcrun simctl list devices | grep -E "iPhone|iPad" | grep -v unavailable | grep Booted | perl -lne 'print $1 if /\((.*?)\)/')
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
booted_simulator=$($DIR/ios_devices.pl "iPhone|iPad" "Booted" "NOT unavailable" | tail -n 1)
echo "IPHONESIMULATOR_DEVICES = $booted_simulator"
xcodebuild test -scheme $1 -destination 'id=0' -destination-timeout 1 2>&1| sed -n 's/{ \(platform:.*\) }/\1/p' | while read destination; do

View File

@ -0,0 +1,50 @@
#!/usr/bin/perl
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is the build configuration utility of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:LGPL21$
## 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 http://www.qt.io/terms-conditions. For further
## information use the contact form at http://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 2.1 or version 3 as published by the Free
## Software Foundation and appearing in the file LICENSE.LGPLv21 and
## LICENSE.LGPLv3 included in the packaging of this file. Please review the
## following information to ensure the GNU Lesser General Public License
## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
##
## As a special exception, The Qt Company gives you certain additional
## rights. These rights are described in The Qt Company LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
## $QT_END_LICENSE$
##
#############################################################################
$output = `xcrun simctl list devices --json 2>&1`;
$output =~ s/\n//g;
BLOCK:
foreach $block ($output =~ /{.*?}/g) {
foreach $filter (@ARGV) {
if ($filter =~ /^NOT\s(.*)/) {
$block =~ /$1/ && next BLOCK;
} else {
$block =~ /$filter/ || next BLOCK;
}
}
$block =~ /udid[:|\s|\"]+(.*)\"/;
print "$1\n";
}

View File

@ -56,11 +56,12 @@ iphonesimulator-install: ACTION = build
release-%: CONFIGURATION = Release
debug-%: CONFIGURATION = Debug
SPECDIR := $(dir $(lastword $(MAKEFILE_LIST)))
# Test and build (device) destinations
ifneq ($(filter check%,$(MAKECMDGOALS)),)
ifeq ($(DEVICES),)
$(info Enumerating test destinations (you may override this by setting DEVICES explicitly), please wait...)
SPECDIR := $(dir $(lastword $(MAKEFILE_LIST)))
DESTINATIONS_INCLUDE = /tmp/ios_destinations.mk
$(shell $(SPECDIR)/ios_destinations.sh $(TARGET) > $(DESTINATIONS_INCLUDE))
include $(DESTINATIONS_INCLUDE)
@ -71,7 +72,7 @@ endif
%-iphoneos: DEVICES = $(IPHONEOS_DEVICES)
IPHONEOS_GENERIC_DESTINATION := "generic/platform=iOS"
IPHONESIMULATOR_GENERIC_DESTINATION := "id=$(shell xcrun simctl list devices | grep -E 'iPhone|iPad' | grep -v unavailable | perl -lne 'print $$1 if /\((.*?)\)/' | tail -n 1)"
IPHONESIMULATOR_GENERIC_DESTINATION := "id=$(shell $(SPECDIR)/ios_devices.pl "iPhone|iPad" "NOT unavailable" | tail -n 1)"
DESTINATION = $(if $(DESTINATION_ID),"id=$(DESTINATION_ID)",$(value $(call toupper,$(call basesdk,$(SDK)))_GENERIC_DESTINATION))

View File

@ -62,7 +62,7 @@
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugDocumentVersioning = "NO"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableReference
@ -88,7 +88,7 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
debugDocumentVersioning = "NO">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"

View File

@ -2693,6 +2693,13 @@
\row
\li version
\li The version number of the package. Defaults to \c{1.0.0.0}.
\row
\li minVersion
\li The minimum required Windows version to run the package. Defaults to the environment variable \c UCRTVersion.
\row
\li maxVersionTested
\li The maximum Windows version the package has been tested against. Defaults to \c WINRT_MANIFEST.minVersion
\endtable
You can use any combination of those values.

View File

@ -576,7 +576,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
QString comment;
QString mainPattern;
const QString preferredLanguage = QLocale::system().name();
const QString preferredLanguage = QLocale().name();
for (QStringList::const_reverse_iterator it = mimeFiles.crbegin(), end = mimeFiles.crend(); it != end; ++it) { // global first, then local.
QFile qfile(*it);

View File

@ -232,15 +232,15 @@ QString QMimeType::name() const
/*!
Returns the description of the MIME type to be displayed on user interfaces.
The system language (QLocale::system().name()) is used to select the appropriate translation.
The default language (QLocale().name()) is used to select the appropriate translation.
*/
QString QMimeType::comment() const
{
QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
QStringList languageList;
languageList << QLocale::system().name();
languageList << QLocale::system().uiLanguages();
languageList << QLocale().name();
languageList << QLocale().uiLanguages();
Q_FOREACH (const QString &language, languageList) {
const QString lang = language == QLatin1String("C") ? QLatin1String("en_US") : language;
const QString comm = d->localeComments.value(lang);

View File

@ -835,8 +835,11 @@ QPixmap QIcon::pixmap(QWindow *window, const QSize &size, Mode mode, State state
qreal devicePixelRatio = qt_effective_device_pixel_ratio(window);
// Handle the simple normal-dpi case:
if (!(devicePixelRatio > 1.0))
return d->engine->pixmap(size, mode, state);
if (!(devicePixelRatio > 1.0)) {
QPixmap pixmap = d->engine->pixmap(size, mode, state);
pixmap.setDevicePixelRatio(1.0);
return pixmap;
}
// Try get a pixmap that is big enough to be displayed at device pixel resolution.
QPixmap pixmap = d->engine->pixmap(size * devicePixelRatio, mode, state);

View File

@ -405,7 +405,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
static const struct {
int key;
const char* name;
const char name[25];
} keyname[] = {
//: This and all following "incomprehensible" strings in QShortcut context
//: are key names. Please use the localized names appearing on actual
@ -687,8 +687,8 @@ static const struct {
{ Qt::Key_TouchpadOn, QT_TRANSLATE_NOOP("QShortcut", "Touchpad On") },
{ Qt::Key_TouchpadOff, QT_TRANSLATE_NOOP("QShortcut", "Touchpad Off") },
{ 0, 0 }
};
static Q_CONSTEXPR int numKeyNames = sizeof keyname / sizeof *keyname;
/*!
\enum QKeySequence::StandardKey
@ -1172,7 +1172,7 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
for (int tran = 0; tran < 2; ++tran) {
if (!nativeText)
++tran;
for (int i = 0; keyname[i].name; ++i) {
for (int i = 0; i < numKeyNames; ++i) {
QString keyName(tran == 0
? QCoreApplication::translate("QShortcut", keyname[i].name)
: QString::fromLatin1(keyname[i].name));
@ -1311,7 +1311,7 @@ QString QKeySequencePrivate::keyName(int key, QKeySequence::SequenceFormat forma
#if defined(Q_OS_MACX)
NonSymbol:
#endif
while (keyname[i].name) {
while (i < numKeyNames) {
if (key == keyname[i].key) {
p = nativeText ? QCoreApplication::translate("QShortcut", keyname[i].name)
: QString::fromLatin1(keyname[i].name);
@ -1323,7 +1323,7 @@ NonSymbol:
// fall back on the unicode representation of it...
// Or else characters like Qt::Key_aring may not get displayed
// (Really depends on you locale)
if (!keyname[i].name) {
if (i >= numKeyNames) {
if (!QChar::requiresSurrogates(key)) {
p = QChar(ushort(key)).toUpper();
} else {

View File

@ -177,6 +177,7 @@ void QOffscreenSurface::create()
if (QThread::currentThread() != qGuiApp->thread())
qWarning("Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.");
d->offscreenWindow = new QWindow(d->screen);
d->offscreenWindow->setObjectName(QLatin1String("QOffscreenSurface"));
// Remove this window from the global list since we do not want it to be destroyed when closing the app.
// The QOffscreenSurface has to be usable even after exiting the event loop.
QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);

View File

@ -204,6 +204,8 @@ QWindow::~QWindow()
{
destroy();
QGuiApplicationPrivate::window_list.removeAll(this);
if (!QGuiApplicationPrivate::is_app_closing)
QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this);
}
void QWindowPrivate::init()
@ -2158,6 +2160,9 @@ void QWindowPrivate::deliverUpdateRequest()
*/
void QWindow::requestUpdate()
{
Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread(),
"QWindow", "Updates can only be scheduled from the GUI (main) thread");
Q_D(QWindow);
if (d->updateRequestPending || !d->platformWindow)
return;

View File

@ -5754,9 +5754,9 @@ static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int
dg = gamma[dg];
db = gamma[db];
int nr = qt_div_255((sr - dr) * mr) + dr;
int ng = qt_div_255((sg - dg) * mg) + dg;
int nb = qt_div_255((sb - db) * mb) + db;
int nr = qt_div_255(sr * mr + dr * (255 - mr));
int ng = qt_div_255(sg * mg + dg * (255 - mg));
int nb = qt_div_255(sb * mb + db * (255 - mb));
nr = invgamma[nr];
ng = invgamma[ng];
@ -5781,9 +5781,9 @@ static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, in
int alpha = coverage;
int ialpha = 255 - alpha;
int nr = (sr * alpha + ialpha * dr) / 255;
int ng = (sg * alpha + ialpha * dg) / 255;
int nb = (sb * alpha + ialpha * db) / 255;
int nr = qt_div_255(sr * alpha + dr * ialpha);
int ng = qt_div_255(sg * alpha + dg * ialpha);
int nb = qt_div_255(sb * alpha + db * ialpha);
nr = invgamma[nr];
ng = invgamma[ng];

View File

@ -705,6 +705,7 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) {
return t;
}
// qt_div_255 is a fast rounded division by 255 using an approximation that is accurate for all positive 16-bit integers
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; }

View File

@ -1046,46 +1046,45 @@ QByteArray QFontEngine::getSfntTable(uint tag) const
return table;
}
void QFontEngine::clearGlyphCache(const void *key)
void QFontEngine::clearGlyphCache(const void *context)
{
for (QLinkedList<GlyphCacheEntry>::iterator it = m_glyphCaches.begin(), end = m_glyphCaches.end(); it != end; ) {
if (it->context == key)
it = m_glyphCaches.erase(it);
else
++it;
}
m_glyphCaches.remove(context);
}
void QFontEngine::setGlyphCache(const void *key, QFontEngineGlyphCache *data)
void QFontEngine::setGlyphCache(const void *context, QFontEngineGlyphCache *cache)
{
Q_ASSERT(data);
Q_ASSERT(cache);
GlyphCaches &caches = m_glyphCaches[context];
for (GlyphCaches::const_iterator it = caches.constBegin(), end = caches.constEnd(); it != end; ++it) {
if (cache == it->cache.data())
return;
}
// Limit the glyph caches to 4 per context. This covers all 90 degree rotations,
// and limits memory use when there is continuous or random rotation
if (caches.size() == 4)
caches.removeLast();
GlyphCacheEntry entry;
entry.context = key;
entry.cache = data;
if (m_glyphCaches.contains(entry))
return;
// Limit the glyph caches to 4. This covers all 90 degree rotations and limits
// memory use when there is continuous or random rotation
if (m_glyphCaches.size() == 4)
m_glyphCaches.removeLast();
m_glyphCaches.push_front(entry);
entry.cache = cache;
caches.push_front(entry);
}
QFontEngineGlyphCache *QFontEngine::glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const
QFontEngineGlyphCache *QFontEngine::glyphCache(const void *context, GlyphFormat format, const QTransform &transform) const
{
for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) {
QFontEngineGlyphCache *c = it->cache.data();
if (key == it->context
&& format == c->glyphFormat()
&& qtransform_equals_no_translate(c->m_transform, transform)) {
return c;
}
const QHash<const void*, GlyphCaches>::const_iterator caches = m_glyphCaches.constFind(context);
if (caches == m_glyphCaches.cend())
return Q_NULLPTR;
for (GlyphCaches::const_iterator it = caches->begin(), end = caches->end(); it != end; ++it) {
QFontEngineGlyphCache *cache = it->cache.data();
if (format == cache->glyphFormat() && qtransform_equals_no_translate(cache->m_transform, transform))
return cache;
}
return 0;
return Q_NULLPTR;
}
static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
@ -1565,12 +1564,11 @@ QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round)
QFontEngine::GlyphCacheEntry::GlyphCacheEntry()
: context(0)
{
}
QFontEngine::GlyphCacheEntry::GlyphCacheEntry(const GlyphCacheEntry &o)
: context(o.context), cache(o.cache)
: cache(o.cache)
{
}
@ -1580,7 +1578,6 @@ QFontEngine::GlyphCacheEntry::~GlyphCacheEntry()
QFontEngine::GlyphCacheEntry &QFontEngine::GlyphCacheEntry::operator=(const GlyphCacheEntry &o)
{
context = o.context;
cache = o.cache;
return *this;
}

View File

@ -316,12 +316,11 @@ private:
GlyphCacheEntry &operator=(const GlyphCacheEntry &);
const void *context;
QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache;
bool operator==(const GlyphCacheEntry &other) const { return context == other.context && cache == other.cache; }
bool operator==(const GlyphCacheEntry &other) const { return cache == other.cache; }
};
mutable QLinkedList<GlyphCacheEntry> m_glyphCaches;
typedef QLinkedList<GlyphCacheEntry> GlyphCaches;
mutable QHash<const void *, GlyphCaches> m_glyphCaches;
private:
QVariant m_userData;

View File

@ -1309,7 +1309,7 @@ QTextCursor QTextDocument::find(const QString &subString, int from, FindFlags op
//do not include the character given in the position.
if (options & FindBackward) {
--pos ;
if (pos < subString.size())
if (pos < 0)
return QTextCursor();
}

View File

@ -103,12 +103,12 @@
To close the socket, call disconnectFromHost(). QAbstractSocket enters
QAbstractSocket::ClosingState. After all pending data has been written to
the socket, QAbstractSocket actually closes the socket, enters
QAbstractSocket::ClosedState, and emits disconnected(). If you want to
abort a connection immediately, discarding all pending data, call abort()
instead. If the remote host closes the connection, QAbstractSocket will
emit error(QAbstractSocket::RemoteHostClosedError), during which the socket
state will still be ConnectedState, and then the disconnected() signal
will be emitted.
QAbstractSocket::UnconnectedState, and emits disconnected(). If you want
to abort a connection immediately, discarding all pending data, call
abort() instead. If the remote host closes the connection,
QAbstractSocket will emit error(QAbstractSocket::RemoteHostClosedError),
during which the socket state will still be ConnectedState, and then the
disconnected() signal will be emitted.
The port and address of the connected peer is fetched by calling
peerPort() and peerAddress(). peerName() returns the host name of

View File

@ -81,8 +81,11 @@ void *qcgl_createNSOpenGLPixelFormat(const QSurfaceFormat &format)
QVector<NSOpenGLPixelFormatAttribute> attrs;
if (format.swapBehavior() != QSurfaceFormat::SingleBuffer)
if (format.swapBehavior() == QSurfaceFormat::DoubleBuffer
|| format.swapBehavior() == QSurfaceFormat::DefaultSwapBehavior)
attrs.append(NSOpenGLPFADoubleBuffer);
else if (format.swapBehavior() == QSurfaceFormat::TripleBuffer)
attrs.append(NSOpenGLPFATripleBuffer);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {

View File

@ -123,6 +123,9 @@ void QNetworkManagerEngine::setupConfigurations()
// Get active connections.
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
if (activeConnectionsList.contains(acPath.path()))
continue;
QNetworkManagerConnectionActive *activeConnection =
new QNetworkManagerConnectionActive(acPath.path(),this);
activeConnectionsList.insert(acPath.path(), activeConnection);
@ -135,14 +138,6 @@ void QNetworkManagerEngine::setupConfigurations()
connectionInterfaces.insert(activeConnection->connection().path(),device.networkInterface());
}
}
// Get current list of access points.
foreach (const QDBusObjectPath &devicePath, managerInterface->getDevices()) {
locker.unlock();
deviceAdded(devicePath); //add all accesspoints
locker.relock();
}
// Get connections.
foreach (const QDBusObjectPath &settingsPath, systemSettings->listConnections()) {
locker.unlock();
@ -251,11 +246,6 @@ void QNetworkManagerEngine::requestUpdate()
QMetaObject::invokeMethod(this, "updateCompleted", Qt::QueuedConnection);
}
void QNetworkManagerEngine::scanFinished()
{
QMetaObject::invokeMethod(this, "updateCompleted", Qt::QueuedConnection);
}
void QNetworkManagerEngine::interfacePropertiesChanged(const QMap<QString, QVariant> &properties)
{
QMutexLocker locker(&mutex);
@ -397,57 +387,6 @@ void QNetworkManagerEngine::deviceConnectionsChanged(const QStringList &connecti
}
}
void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path)
{
QNetworkManagerInterfaceDevice *iDevice;
iDevice = new QNetworkManagerInterfaceDevice(path.path(),this);
connect(iDevice,SIGNAL(connectionsChanged(QStringList)),
this,SLOT(deviceConnectionsChanged(QStringList)));
interfaceDevices.insert(path.path(),iDevice);
if (iDevice->deviceType() == DEVICE_TYPE_WIFI) {
QNetworkManagerInterfaceDeviceWireless *wirelessDevice =
new QNetworkManagerInterfaceDeviceWireless(iDevice->path(),this);
connect(wirelessDevice, SIGNAL(accessPointAdded(QString)),
this, SLOT(newAccessPoint(QString)));
connect(wirelessDevice, SIGNAL(accessPointRemoved(QString)),
this, SLOT(removeAccessPoint(QString)));
connect(wirelessDevice,SIGNAL(scanDone()),this,SLOT(scanFinished()));
wirelessDevice->setConnections();
wirelessDevices.insert(path.path(), wirelessDevice);
}
if (iDevice->deviceType() == DEVICE_TYPE_ETHERNET) {
QNetworkManagerInterfaceDeviceWired *wiredDevice =
new QNetworkManagerInterfaceDeviceWired(iDevice->path(),this);
connect(wiredDevice,SIGNAL(carrierChanged(bool)),this,SLOT(wiredCarrierChanged(bool)));
wiredDevices.insert(iDevice->path(), wiredDevice);
}
}
void QNetworkManagerEngine::deviceRemoved(const QDBusObjectPath &path)
{
QMutexLocker locker(&mutex);
if (interfaceDevices.contains(path.path())) {
locker.unlock();
delete interfaceDevices.take(path.path());
locker.relock();
}
if (wirelessDevices.contains(path.path())) {
locker.unlock();
delete wirelessDevices.take(path.path());
locker.relock();
}
if (wiredDevices.contains(path.path())) {
locker.unlock();
delete wiredDevices.take(path.path());
locker.relock();
}
}
void QNetworkManagerEngine::wiredCarrierChanged(bool carrier)
{
QNetworkManagerInterfaceDeviceWired *deviceWired = qobject_cast<QNetworkManagerInterfaceDeviceWired *>(sender());
@ -538,7 +477,7 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
if (i.value()->deviceType() == deviceType) {
QNetworkManagerInterfaceDeviceWired *wiredDevice
= wiredDevices.value(i.value()->path());
if (wiredDevice->carrier()) {
if (wiredDevice && wiredDevice->carrier()) {
cpPriv->state |= QNetworkConfiguration::Discovered;
}
}
@ -596,15 +535,10 @@ void QNetworkManagerEngine::removeConnection(const QString &path)
emit configurationRemoved(ptr);
locker.relock();
}
// add base AP back into configurations
QMapIterator<QString, QString> i(configuredAccessPoints);
while (i.hasNext()) {
i.next();
if (i.value() == path) {
configuredAccessPoints.remove(i.key());
newAccessPoint(i.key());
}
}
// removed along with all AP props code...
}
void QNetworkManagerEngine::updateConnection()
@ -678,114 +612,6 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher)
}
}
void QNetworkManagerEngine::newAccessPoint(const QString &path)
{
QMutexLocker locker(&mutex);
QNetworkManagerInterfaceAccessPoint *accessPoint =
new QNetworkManagerInterfaceAccessPoint(path,this);
bool okToAdd = true;
for (int i = 0; i < accessPoints.count(); ++i) {
if (accessPoints.at(i)->path() == path) {
okToAdd = false;
}
}
if (okToAdd) {
accessPoints.append(accessPoint);
}
// Check if configuration exists for connection.
if (!accessPoint->ssid().isEmpty()) {
for (int i = 0; i < connections.count(); ++i) {
QNetworkManagerSettingsConnection *connection = connections.at(i);
const QString settingsPath = connection->path();
if (accessPoint->ssid() == connection->getSsid()) {
if (!configuredAccessPoints.contains(path)) {
configuredAccessPoints.insert(path,settingsPath);
}
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.value(settingsPath);
ptr->mutex.lock();
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
ptr->state = (flag | QNetworkConfiguration::Discovered);
if (isConnectionActive(settingsPath))
ptr->state = (flag | QNetworkConfiguration::Active);
ptr->mutex.unlock();
locker.unlock();
emit configurationChanged(ptr);
return;
}
}
}
// New access point.
QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
ptr->name = accessPoint->ssid();
ptr->isValid = true;
ptr->id = path;
ptr->type = QNetworkConfiguration::InternetAccessPoint;
ptr->purpose = QNetworkConfiguration::PublicPurpose;
ptr->state = QNetworkConfiguration::Undefined;
ptr->bearerType = QNetworkConfiguration::BearerWLAN;
accessPointConfigurations.insert(ptr->id, ptr);
locker.unlock();
emit configurationAdded(ptr);
}
void QNetworkManagerEngine::removeAccessPoint(const QString &path)
{
QMutexLocker locker(&mutex);
for (int i = 0; i < accessPoints.count(); ++i) {
QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i);
if (accessPoint->path() == path) {
accessPoints.removeOne(accessPoint);
if (configuredAccessPoints.contains(accessPoint->path())) {
// find connection and change state to Defined
configuredAccessPoints.remove(accessPoint->path());
for (int i = 0; i < connections.count(); ++i) {
QNetworkManagerSettingsConnection *connection = connections.at(i);
if (accessPoint->ssid() == connection->getSsid()) {//might not have bssid yet
const QString settingsPath = connection->path();
const QString connectionId = settingsPath;
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.value(connectionId);
ptr->mutex.lock();
ptr->state = QNetworkConfiguration::Defined;
ptr->mutex.unlock();
locker.unlock();
emit configurationChanged(ptr);
locker.relock();
break;
}
}
} else {
QNetworkConfigurationPrivatePointer ptr =
accessPointConfigurations.take(path);
if (ptr) {
locker.unlock();
emit configurationRemoved(ptr);
locker.relock();
}
}
delete accessPoint;
break;
}
}
}
QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &settingsPath,
const QNmSettingsMap &map)
{
@ -808,7 +634,7 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
QNetworkManagerInterfaceDevice device(devicePath.path(),this);
if (device.deviceType() == DEVICE_TYPE_ETHERNET) {
QNetworkManagerInterfaceDeviceWired *wiredDevice = wiredDevices.value(device.path());
if (wiredDevice->carrier()) {
if (wiredDevice && wiredDevice->carrier()) {
cpPriv->state |= QNetworkConfiguration::Discovered;
break;
}
@ -1078,10 +904,6 @@ void QNetworkManagerEngine::nmRegistered(const QString &)
managerInterface = new QNetworkManagerInterface(this);
systemSettings = new QNetworkManagerSettings(NM_DBUS_SERVICE, this);
connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)),
this, SLOT(deviceAdded(QDBusObjectPath)));
connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)),
this, SLOT(deviceRemoved(QDBusObjectPath)));
connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
this, SLOT(activationFinished(QDBusPendingCallWatcher*)));
connect(managerInterface, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),

View File

@ -93,19 +93,12 @@ private Q_SLOTS:
void interfacePropertiesChanged(const QMap<QString, QVariant> &properties);
void activeConnectionPropertiesChanged(const QMap<QString, QVariant> &properties);
void deviceAdded(const QDBusObjectPath &path);
void deviceRemoved(const QDBusObjectPath &path);
void newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings = 0);
void removeConnection(const QString &path);
void updateConnection();
void activationFinished(QDBusPendingCallWatcher *watcher);
void deviceConnectionsChanged(const QStringList &activeConnectionsList);
void newAccessPoint(const QString &path);
void removeAccessPoint(const QString &path);
void scanFinished();
void wiredCarrierChanged(bool);
void nmRegistered(const QString &serviceName = QString());

View File

@ -95,6 +95,21 @@ QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent)
QNetworkManagerInterface::~QNetworkManagerInterface()
{
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
QLatin1String(NM_DBUS_PATH),
QLatin1String(NM_DBUS_INTERFACE),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
QLatin1String(NM_DBUS_PATH),
QLatin1String(NM_DBUS_INTERFACE),
QLatin1String("DeviceAdded"),
this,SIGNAL(deviceAdded(QDBusObjectPath)));
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
QLatin1String(NM_DBUS_PATH),
QLatin1String(NM_DBUS_INTERFACE),
QLatin1String("DeviceRemoved"),
this,SIGNAL(deviceRemoved(QDBusObjectPath)));
}
bool QNetworkManagerInterface::setConnections()
@ -235,28 +250,6 @@ QNetworkManagerInterfaceAccessPoint::QNetworkManagerInterfaceAccessPoint(const Q
NM_DBUS_INTERFACE_ACCESS_POINT,
QDBusConnection::systemBus(),parent)
{
if (!isValid()) {
return;
}
PropertiesDBusInterface *accessPointPropertiesInterface = new PropertiesDBusInterface(QLatin1String(NM_DBUS_SERVICE),
dbusPathName,
DBUS_PROPERTIES_INTERFACE,
QDBusConnection::systemBus());
QList<QVariant> argumentList;
argumentList << QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT);
QDBusPendingReply<QVariantMap> propsReply
= accessPointPropertiesInterface->callWithArgumentList(QDBus::Block,QLatin1String("GetAll"),
argumentList);
if (!propsReply.isError()) {
propertyMap = propsReply.value();
}
QDBusConnection::systemBus().connect(QLatin1String(NM_DBUS_SERVICE),
dbusPathName,
QLatin1String(NM_DBUS_INTERFACE_ACCESS_POINT),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
}
QNetworkManagerInterfaceAccessPoint::~QNetworkManagerInterfaceAccessPoint()
@ -369,6 +362,11 @@ QNetworkManagerInterfaceDevice::QNetworkManagerInterfaceDevice(const QString &de
QNetworkManagerInterfaceDevice::~QNetworkManagerInterfaceDevice()
{
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
path(),
QLatin1String(NM_DBUS_INTERFACE_DEVICE),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
}
QString QNetworkManagerInterfaceDevice::udi() const
@ -468,6 +466,11 @@ QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const Q
QNetworkManagerInterfaceDeviceWired::~QNetworkManagerInterfaceDeviceWired()
{
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
path(),
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRED),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
}
QString QNetworkManagerInterfaceDeviceWired::hwAddress() const
@ -557,77 +560,20 @@ QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(c
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
QDBusPendingReply<QList<QDBusObjectPath> > reply
= asyncCall(QLatin1String("GetAccessPoints"));
QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(reply);
connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
this, SLOT(accessPointsFinished(QDBusPendingCallWatcher*)));
}
QNetworkManagerInterfaceDeviceWireless::~QNetworkManagerInterfaceDeviceWireless()
{
}
void QNetworkManagerInterfaceDeviceWireless::slotAccessPointAdded(QDBusObjectPath path)
{
if (path.path().length() > 2)
Q_EMIT accessPointAdded(path.path());
}
void QNetworkManagerInterfaceDeviceWireless::slotAccessPointRemoved(QDBusObjectPath path)
{
if (path.path().length() > 2)
Q_EMIT accessPointRemoved(path.path());
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
path(),
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
}
bool QNetworkManagerInterfaceDeviceWireless::setConnections()
{
if (!isValid())
return false;
QDBusConnection dbusConnection = QDBusConnection::systemBus();
bool allOk = true;
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
interfacePath,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("AccessPointAdded"),
this, SLOT(slotAccessPointAdded(QDBusObjectPath)))) {
allOk = false;
}
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
interfacePath,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("AccessPointRemoved"),
this, SLOT(slotAccessPointRemoved(QDBusObjectPath)))) {
allOk = false;
}
if (!dbusConnection.connect(QLatin1String(NM_DBUS_SERVICE),
interfacePath,
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("ScanDone"),
this, SLOT(scanIsDone()))) {
allOk = false;
}
return allOk;
}
void QNetworkManagerInterfaceDeviceWireless::accessPointsFinished(QDBusPendingCallWatcher *watcher)
{
QDBusPendingReply<QList<QDBusObjectPath> > reply(*watcher);
watcher->deleteLater();
if (!reply.isError()) {
accessPointsList = reply.value();
}
for (int i = 0; i < accessPointsList.size(); i++) {
Q_EMIT accessPointAdded(accessPointsList.at(i).path());
}
return true;
}
QList <QDBusObjectPath> QNetworkManagerInterfaceDeviceWireless::getAccessPoints()
@ -676,11 +622,6 @@ quint32 QNetworkManagerInterfaceDeviceWireless::wirelessCapabilities() const
return 0;
}
void QNetworkManagerInterfaceDeviceWireless::scanIsDone()
{
Q_EMIT scanDone();
}
void QNetworkManagerInterfaceDeviceWireless::requestScan()
{
asyncCall(QLatin1String("RequestScan"));
@ -729,6 +670,12 @@ QNetworkManagerInterfaceDeviceModem::QNetworkManagerInterfaceDeviceModem(const Q
QNetworkManagerInterfaceDeviceModem::~QNetworkManagerInterfaceDeviceModem()
{
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
path(),
QLatin1String(NM_DBUS_PATH_SETTINGS),
QLatin1String(NM_DBUS_IFACE_SETTINGS),
QLatin1String("NewConnection"),
this, SIGNAL(newConnection(QDBusObjectPath)));
}
QNetworkManagerInterfaceDeviceModem::ModemCapabilities QNetworkManagerInterfaceDeviceModem::modemCapabilities() const
@ -833,6 +780,16 @@ QNetworkManagerSettingsConnection::QNetworkManagerSettingsConnection(const QStri
QNetworkManagerSettingsConnection::~QNetworkManagerSettingsConnection()
{
QDBusConnection::systemBus().disconnect(service(),
path(),
QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION),
QLatin1String("Updated"),
this, SIGNAL(updated()));
QDBusConnection::systemBus().disconnect(service(),
path(),
QLatin1String(NM_DBUS_IFACE_SETTINGS_CONNECTION),
QLatin1String("Removed"),
this, SIGNAL(slotSettingsRemoved()));
}
bool QNetworkManagerSettingsConnection::setConnections()
@ -989,6 +946,11 @@ QNetworkManagerConnectionActive::QNetworkManagerConnectionActive(const QString &
QNetworkManagerConnectionActive::~QNetworkManagerConnectionActive()
{
QDBusConnection::systemBus().disconnect(QLatin1String(NM_DBUS_SERVICE),
path(),
QLatin1String(NM_DBUS_INTERFACE_ACTIVE_CONNECTION),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
}
QDBusObjectPath QNetworkManagerConnectionActive::connection() const

View File

@ -322,7 +322,6 @@ public:
QObject *parent = 0);
~QNetworkManagerInterfaceDeviceWireless();
QDBusObjectPath path() const;
QList <QDBusObjectPath> getAccessPoints();
QString hwAddress() const;
@ -335,21 +334,11 @@ public:
void requestScan();
Q_SIGNALS:
void propertiesChanged(QMap<QString,QVariant>);
void accessPointAdded(const QString &);
void accessPointRemoved(const QString &);
void scanDone();
void propertiesReady();
void accessPointsReady();
private Q_SLOTS:
void scanIsDone();
void propertiesSwap(QMap<QString,QVariant>);
void slotAccessPointAdded(QDBusObjectPath);
void slotAccessPointRemoved(QDBusObjectPath);
void accessPointsFinished(QDBusPendingCallWatcher *watcher);
private:
QVariantMap propertyMap;
QList <QDBusObjectPath> accessPointsList;

View File

@ -305,8 +305,16 @@ void QCocoaGLContext::updateSurfaceFormat()
m_format.setSamples(samples);
int doubleBuffered = -1;
int tripleBuffered = -1;
[pixelFormat getValues:&doubleBuffered forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:0];
m_format.setSwapBehavior(doubleBuffered == 1 ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
[pixelFormat getValues:&tripleBuffered forAttribute:NSOpenGLPFATripleBuffer forVirtualScreen:0];
if (tripleBuffered == 1)
m_format.setSwapBehavior(QSurfaceFormat::TripleBuffer);
else if (doubleBuffered == 1)
m_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
else
m_format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
int steroBuffers = -1;
[pixelFormat getValues:&steroBuffers forAttribute:NSOpenGLPFAStereo forVirtualScreen:0];

View File

@ -908,7 +908,7 @@
UIFont *uifont = [UIFont fontWithName:qfont.family().toNSString() size:qfont.pointSize()];
if (!uifont)
return [NSDictionary dictionary];
return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey];
return [NSDictionary dictionaryWithObject:uifont forKey:NSFontAttributeName];
}
- (NSDictionary *)markedTextStyle

View File

@ -1044,12 +1044,15 @@ void QWindowsNativeFileDialogBase::setDirectory(const QUrl &directory)
QString QWindowsNativeFileDialogBase::directory() const
{
QString result;
#ifndef Q_OS_WINCE
IShellItem *item = 0;
if (m_fileDialog && SUCCEEDED(m_fileDialog->GetFolder(&item)) && item)
return QWindowsNativeFileDialogBase::itemPath(item);
if (m_fileDialog && SUCCEEDED(m_fileDialog->GetFolder(&item)) && item) {
result = QWindowsNativeFileDialogBase::itemPath(item);
item->Release();
}
#endif
return QString();
return result;
}
void QWindowsNativeFileDialogBase::doExec(HWND owner)
@ -1514,8 +1517,10 @@ QList<QUrl> QWindowsNativeSaveFileDialog::selectedFiles() const
QList<QUrl> result;
IShellItem *item = 0;
const HRESULT hr = fileDialog()->GetCurrentSelection(&item);
if (SUCCEEDED(hr) && item)
if (SUCCEEDED(hr) && item) {
result.push_back(QUrl::fromLocalFile(QWindowsNativeSaveFileDialog::itemPath(item)));
item->Release();
}
return result;
}

View File

@ -56,6 +56,7 @@ typedef IEventHandler<IInspectable *> ContentChangedHandler;
QT_BEGIN_NAMESPACE
QWinRTClipboard::QWinRTClipboard()
: m_mimeData(Q_NULLPTR)
{
#ifndef Q_OS_WINPHONE
QEventDispatcherWinRT::runOnXamlThread([this]() {
@ -100,9 +101,16 @@ QMimeData *QWinRTClipboard::mimeData(QClipboard::Mode mode)
const wchar_t *textStr = result.GetRawBuffer(&size);
QString text = QString::fromWCharArray(textStr, size);
text.replace(QStringLiteral("\r\n"), QStringLiteral("\n"));
m_mimeData.setText(text);
return &m_mimeData;
if (m_mimeData) {
if (m_mimeData->text() == text)
return m_mimeData;
delete m_mimeData;
}
m_mimeData = new QMimeData();
m_mimeData->setText(text);
return m_mimeData;
#else // Q_OS_WINPHONE
return QPlatformClipboard::mimeData(mode);
#endif // Q_OS_WINPHONE
@ -143,6 +151,12 @@ void QWinRTClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
return;
#ifndef Q_OS_WINPHONE
const bool newData = !m_mimeData || m_mimeData != data;
if (newData) {
if (m_mimeData)
delete m_mimeData;
m_mimeData = data;
}
const QString text = data ? data->text() : QString();
HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, text]() {
HRESULT hr;
@ -161,7 +175,6 @@ void QWinRTClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
return S_OK;
});
RETURN_VOID_IF_FAILED("Could not set clipboard text.");
emitChanged(mode);
#else // Q_OS_WINPHONE
QPlatformClipboard::setMimeData(data, mode);
#endif // Q_OS_WINPHONE

View File

@ -70,7 +70,7 @@ private:
#ifndef Q_OS_WINPHONE
Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::DataTransfer::IClipboardStatics> m_nativeClipBoard;
#endif
QMimeData m_mimeData;
QMimeData *m_mimeData;
};
QT_END_NAMESPACE

View File

@ -108,6 +108,9 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa
Q_D(QWinRTMessageDialogHelper);
QSharedPointer<QMessageDialogOptions> options = this->options();
if (!options.data())
return false;
const QString informativeText = options->informativeText();
const QString title = options->windowTitle();
const QString text = informativeText.isEmpty() ? options->text() : (options->text() + QLatin1Char('\n') + informativeText);

View File

@ -3,6 +3,8 @@ QT += core-private gui-private platformsupport-private xcb_qpa_lib-private
INCLUDEPATH += $$PWD
INCLUDEPATH += $$PWD/../
load(qt_build_paths)
# needed by Xcursor ...
contains(QT_CONFIG, xcb-xlib) {
DEFINES += XCB_USE_XLIB

View File

@ -38,6 +38,8 @@ HEADERS = \
qxcbxsettings.h \
qxcbsystemtraytracker.h
load(qt_build_paths)
DEFINES += QT_BUILD_XCB_PLUGIN
# needed by Xcursor ...
contains(QT_CONFIG, xcb-xlib) {

View File

@ -918,14 +918,14 @@ void QWin32PrintEnginePrivate::initialize()
Q_ASSERT(hPrinter);
Q_ASSERT(pInfo);
initHDC();
if (devMode) {
num_copies = devMode->dmCopies;
devMode->dmCollate = DMCOLLATE_TRUE;
updatePageLayout();
}
initHDC();
#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS
qDebug() << "QWin32PrintEngine::initialize()";
debugMetrics();

View File

@ -124,10 +124,14 @@ public:
state(QPrinter::Idle),
resolution(0),
m_pageLayout(QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(0, 0, 0, 0))),
stretch_x(1), stretch_y(1), origin_x(0), origin_y(0),
dpi_x(96), dpi_y(96), dpi_display(96),
num_copies(1),
printToFile(false),
reinit(false),
embed_fonts(true)
complex_xform(false), has_pen(false), has_brush(false), has_custom_paper_size(false),
embed_fonts(true),
txop(0 /* QTransform::TxNone */)
{
}

View File

@ -2173,7 +2173,8 @@ QColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QStr
QRgb QColorDialog::getRgba(QRgb initial, bool *ok, QWidget *parent)
{
QColor color(getColor(QColor(initial), parent, QString(), ShowAlphaChannel));
const QColor color = getColor(QColor::fromRgba(initial), parent, QString(),
ShowAlphaChannel);
QRgb result = color.isValid() ? color.rgba() : initial;
if (ok)
*ok = color.isValid();

View File

@ -10340,14 +10340,13 @@ void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
// the old type was a window and/or the new type is a window
QPoint oldPos = q->pos();
bool visible = q->isVisible();
const bool windowFlagChanged = (q->data->window_flags ^ flags) & Qt::Window;
q->setParent(q->parentWidget(), flags);
// if both types are windows or neither of them are, we restore
// the old position
if (!((q->data->window_flags ^ flags) & Qt::Window)
&& (visible || q->testAttribute(Qt::WA_Moved))) {
if (!windowFlagChanged && (visible || q->testAttribute(Qt::WA_Moved)))
q->move(oldPos);
}
// for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
adjustQuitOnCloseAttribute();
} else {

View File

@ -996,15 +996,17 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject
}
}
if (const QWidget *widget = qobject_cast<const QWidget *>(object)) {
QStyleSheetStyle *style = const_cast<QStyleSheetStyle *>(globalStyleSheetStyle);
if (!style)
style = qobject_cast<QStyleSheetStyle *>(widget->style());
if (style)
fixupBorder(style->nativeFrameWidth(widget));
if (hasBorder()) {
if (const QWidget *widget = qobject_cast<const QWidget *>(object)) {
QStyleSheetStyle *style = const_cast<QStyleSheetStyle *>(globalStyleSheetStyle);
if (!style)
style = qobject_cast<QStyleSheetStyle *>(widget->style());
if (style)
fixupBorder(style->nativeFrameWidth(widget));
}
if (border()->hasBorderImage())
defaultBackground = QBrush();
}
if (hasBorder() && border()->hasBorderImage())
defaultBackground = QBrush();
}
QRect QRenderRule::borderRect(const QRect& r) const

View File

@ -1175,9 +1175,9 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
case CE_MenuItem:
if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
// windows always has a check column, regardless whether we have an icon or not
const qreal devicePixelRatio = QWindowsXPStylePrivate::devicePixelRatio(widget);
int checkcol = qRound(qreal(25) / devicePixelRatio);
const int gutterWidth = qRound(qreal(3) / devicePixelRatio);
const qreal factor = QWindowsXPStylePrivate::nativeMetricScaleFactor(widget);
int checkcol = qRound(qreal(25) * factor);
const int gutterWidth = qRound(qreal(3) * factor);
{
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme,
MENU_POPUPCHECKBACKGROUND, MBI_HOT);
@ -2166,8 +2166,9 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
const bool isToolTitle = false;
const int height = tb->rect.height();
const int width = tb->rect.width();
int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget)
- int(QStyleHelper::dpiScaled(4));
const int buttonWidth =
qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * QWindowsStylePrivate::nativeMetricScaleFactor(widget)
- QStyleHelper::dpiScaled(4));
const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;

View File

@ -2098,7 +2098,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
themeNumber = QWindowsXPStylePrivate::StatusTheme;
partId = SP_GRIPPER;
XPThemeData theme(0, p, themeNumber, partId, 0);
QSize size = (theme.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize();
QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
size.rheight()--;
if (const QStyleOptionSizeGrip *sg = qstyleoption_cast<const QStyleOptionSizeGrip *>(option)) {
switch (sg->corner) {
@ -2169,7 +2169,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QWindowsXPStylePrivate::ToolBarTheme,
TP_SPLITBUTTONDROPDOWN);
if (theme.isValid()) {
const QSize size = (theme.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize();
const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
mbiw = size.width();
mbih = size.height();
}
@ -2632,10 +2632,11 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const QWidget *widget, XPThemeData *theme)
{
const bool horizontal = flags & QStyle::State_Horizontal;
const QMargins contentsMargin = (theme->margins(theme->rect, TMT_SIZINGMARGINS)
/ QWindowsStylePrivate::devicePixelRatio(widget)).toMargins();
const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget);
const QMargins contentsMargin =
(theme->margins(theme->rect, TMT_SIZINGMARGINS) * factor).toMargins();
theme->partId = horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT;
const QSize size = (theme->size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize();
const QSize size = (theme->size() * factor).toSize();
const int hSpace = theme->rect.width() - size.width();
const int vSpace = theme->rect.height() - size.height();
@ -3793,12 +3794,13 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt
{
XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL);
if (buttontheme.isValid()) {
const qreal devicePixelRatio = QWindowsXPStylePrivate::devicePixelRatio(widget);
const QMarginsF borderSize = buttontheme.margins() / devicePixelRatio;
const qreal factor = QWindowsXPStylePrivate::nativeMetricScaleFactor(widget);
const QMarginsF borderSize = buttontheme.margins() * factor;
if (!borderSize.isNull()) {
const qreal margin = qreal(2) / devicePixelRatio;
const qreal margin = qreal(2) * factor;
sz.rwidth() += qRound(borderSize.left() + borderSize.right() - margin);
sz.rheight() += int(borderSize.bottom() + borderSize.top() - margin + devicePixelRatio - 1);
sz.rheight() += int(borderSize.bottom() + borderSize.top() - margin
+ qreal(1) / factor - 1);
}
const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1);
sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget)
@ -4072,7 +4074,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_RESTOREBUTTON, RBS_NORMAL);
if (theme.isValid()) {
const QSize size = (themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize();
const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
QPixmap pm(size);
pm.fill(Qt::transparent);
QPainter p(&pm);

View File

@ -1083,6 +1083,8 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event)
}
d->edit->event(event);
if (!d->edit->text().isEmpty())
d->cleared = false;
if (!isVisible())
d->ignoreUpdateEdit = true;
}

View File

@ -2604,6 +2604,21 @@ void QDockAreaLayout::remove(const QList<int> &path)
docks[index].remove(path.mid(1));
}
void QDockAreaLayout::removePlaceHolder(const QString &name)
{
QList<int> index = indexOfPlaceHolder(name);
if (!index.isEmpty())
remove(index);
foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>(
QString(), Qt::FindDirectChildrenOnly)) {
index = dwgw->layoutInfo()->indexOfPlaceHolder(name);
if (!index.isEmpty()) {
dwgw->layoutInfo()->remove(index);
dwgw->destroyOrHideIfEmpty();
}
}
}
static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
@ -3030,15 +3045,27 @@ QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget)
bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
{
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (index.isEmpty())
return false;
QDockAreaLayoutItem *item = 0;
foreach (QDockWidgetGroupWindow *dwgw, mainWindow->findChildren<QDockWidgetGroupWindow *>(
QString(), Qt::FindDirectChildrenOnly)) {
QList<int> index = dwgw->layoutInfo()->indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty()) {
dockWidget->setParent(dwgw);
item = const_cast<QDockAreaLayoutItem *>(&dwgw->layoutInfo()->item(index));
break;
}
}
if (!item) {
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (index.isEmpty())
return false;
item = const_cast<QDockAreaLayoutItem *>(&this->item(index));
}
QDockAreaLayoutItem &item = this->item(index);
QPlaceHolderItem *placeHolder = item.placeHolderItem;
QPlaceHolderItem *placeHolder = item->placeHolderItem;
Q_ASSERT(placeHolder != 0);
item.widgetItem = new QDockWidgetItem(dockWidget);
item->widgetItem = new QDockWidgetItem(dockWidget);
if (placeHolder->window) {
const QRect r = constrainedRect(placeHolder->topLevelRect, dockWidget);
@ -3050,7 +3077,7 @@ bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
dockWidget->d_func()->setWindowState(true);
#endif
item.placeHolderItem = 0;
item->placeHolderItem = 0;
delete placeHolder;
return true;
@ -3086,9 +3113,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do
info = new_info;
}
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty())
remove(index);
removePlaceHolder(dockWidget->objectName());
}
void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
@ -3101,9 +3126,7 @@ void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
Q_ASSERT(info != 0);
info->tab(path.last(), new QDockWidgetItem(second));
QList<int> index = indexOfPlaceHolder(second->objectName());
if (!index.isEmpty())
remove(index);
removePlaceHolder(second->objectName());
}
void QDockAreaLayout::resizeDocks(const QList<QDockWidget *> &docks,
@ -3165,9 +3188,7 @@ void QDockAreaLayout::splitDockWidget(QDockWidget *after,
Q_ASSERT(info != 0);
info->split(path.last(), orientation, new QDockWidgetItem(dockWidget));
QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
if (!index.isEmpty())
remove(index);
removePlaceHolder(dockWidget->objectName());
}
void QDockAreaLayout::apply(bool animate)

View File

@ -255,6 +255,7 @@ public:
QLayoutItem *plug(const QList<int> &path);
QLayoutItem *unplug(const QList<int> &path);
void remove(const QList<int> &path);
void removePlaceHolder(const QString &name);
void fitLayout();

View File

@ -215,11 +215,10 @@ public:
}
void setGeometry(const QRect&r) Q_DECL_OVERRIDE
{
static_cast<QDockWidgetGroupWindow *>(parent())->destroyOrHideIfEmpty();
QDockAreaLayoutInfo *li = layoutInfo();
if (li->isEmpty()) {
static_cast<QDockWidgetGroupWindow *>(parent())->destroyIfEmpty();
if (li->isEmpty())
return;
}
int fw = frameWidth();
li->reparentWidgets(parentWidget());
li->rect = r.adjusted(fw, fw, -fw, -fw);
@ -272,6 +271,10 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
if (qobject_cast<QDockWidget *>(static_cast<QChildEvent*>(e)->child()))
adjustFlags();
break;
case QEvent::LayoutRequest:
// We might need to show the widget again
destroyOrHideIfEmpty();
break;
default:
break;
}
@ -325,34 +328,43 @@ QDockWidget *QDockWidgetGroupWindow::topDockWidget() const
}
/*! \internal
Destroy this window if there is no more QDockWidget in it.
Destroy or hide this window if there is no more QDockWidget in it.
Otherwise make sure it is shown.
*/
void QDockWidgetGroupWindow::destroyIfEmpty()
void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
{
if (layoutInfo()->isEmpty()) {
// Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
foreach (QDockWidget *dw,
findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly)) {
bool wasFloating = dw->isFloating();
bool wasHidden = dw->isHidden();
dw->setParent(parentWidget());
if (wasFloating) {
dw->setFloating(true);
} else {
// maybe it was hidden, we still have to put it back in the main layout.
QMainWindowLayout *ml = qt_mainwindow_layout(static_cast<QMainWindow*>(parentWidget()));
Qt::DockWidgetArea area = ml->dockWidgetArea(this);
if (area == Qt::NoDockWidgetArea)
area = Qt::LeftDockWidgetArea;
static_cast<QMainWindow*>(parentWidget())->addDockWidget(area, dw);
}
if (!wasHidden)
dw->show();
}
foreach (QTabBar *tb, findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly))
tb->setParent(parentWidget());
deleteLater();
if (!layoutInfo()->isEmpty()) {
show(); // It might have been hidden,
return;
}
// There might still be placeholders
if (!layoutInfo()->item_list.isEmpty()) {
hide();
return;
}
// Make sure to reparent the possibly floating or hidden QDockWidgets to the parent
foreach (QDockWidget *dw, findChildren<QDockWidget *>(QString(), Qt::FindDirectChildrenOnly)) {
bool wasFloating = dw->isFloating();
bool wasHidden = dw->isHidden();
dw->setParent(parentWidget());
if (wasFloating) {
dw->setFloating(true);
} else {
// maybe it was hidden, we still have to put it back in the main layout.
QMainWindowLayout *ml =
qt_mainwindow_layout(static_cast<QMainWindow *>(parentWidget()));
Qt::DockWidgetArea area = ml->dockWidgetArea(this);
if (area == Qt::NoDockWidgetArea)
area = Qt::LeftDockWidgetArea;
static_cast<QMainWindow *>(parentWidget())->addDockWidget(area, dw);
}
if (!wasHidden)
dw->show();
}
foreach (QTabBar *tb, findChildren<QTabBar *>(QString(), Qt::FindDirectChildrenOnly))
tb->setParent(parentWidget());
deleteLater();
}
/*! \internal
@ -2075,7 +2087,7 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
item.subinfo->reparentWidgets(parentWidget());
item.subinfo->setTabBarShape(parentInfo->tabBarShape);
}
dwgw->destroyIfEmpty();
dwgw->destroyOrHideIfEmpty();
}
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {

View File

@ -86,7 +86,7 @@ public:
: QWidget(parent, f) {}
QDockAreaLayoutInfo *layoutInfo() const;
QDockWidget *topDockWidget() const;
void destroyIfEmpty();
void destroyOrHideIfEmpty();
void adjustFlags();
protected:
bool event(QEvent *) Q_DECL_OVERRIDE;

View File

@ -132,6 +132,7 @@ tst_QMimeDatabase::tst_QMimeDatabase()
void tst_QMimeDatabase::initTestCase()
{
QLocale::setDefault(QLocale::c());
QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString()));
QStandardPaths::setTestModeEnabled(true);
m_localMimeDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/mime";
@ -450,6 +451,21 @@ void tst_QMimeDatabase::icons()
QCOMPARE(pub.genericIconName(), QString::fromLatin1("x-office-document"));
}
void tst_QMimeDatabase::comment()
{
struct RestoreLocale
{
~RestoreLocale() { QLocale::setDefault(QLocale::c()); }
} restoreLocale;
QLocale::setDefault(QLocale("de"));
QMimeDatabase db;
QMimeType directory = db.mimeTypeForName(QStringLiteral("inode/directory"));
QCOMPARE(directory.comment(), QStringLiteral("Ordner"));
QLocale::setDefault(QLocale("fr"));
QCOMPARE(directory.comment(), QStringLiteral("dossier"));
}
// In here we do the tests that need some content in a temporary file.
// This could also be added to shared-mime-info's testsuite...
void tst_QMimeDatabase::mimeTypeForFileWithContent()

View File

@ -60,6 +60,7 @@ private slots:
void listAliases_data();
void listAliases();
void icons();
void comment();
void mimeTypeForFileWithContent();
void mimeTypeForUrl();
void mimeTypeForData_data();

View File

@ -323,6 +323,8 @@ void tst_QTextDocument::find_data()
<< 15 << 6 << 11;
QTest::newRow("nbsp") << "Hello" + QString(QChar(QChar::Nbsp)) +"World" << " " << int(QTextDocument::FindCaseSensitively) << 0 << 5 << 6;
QTest::newRow("from-the-end") << "Hello World" << "Hello World" << int(QTextDocument::FindCaseSensitively| QTextDocument::FindBackward) << 11 << 0 << 11;
}
void tst_QTextDocument::find()

View File

@ -32,89 +32,185 @@
##
#############################################################################
#regenerate all test's output
# Regenerate all tests' output.
#
# Usage: cd to the build directory corresponding to this script's
# location; invoke this script; optionally pass the names of sub-dirs
# to limit which tests to regenerate expected_* files for.
import os
import sys
import subprocess
import re
formats = ['xml', 'txt', 'xunitxml', 'lightxml']
class Fail (Exception): pass
qtver = subprocess.check_output(['qmake', '-query', 'QT_VERSION']).strip().decode('utf-8')
rootPath = os.getcwd()
class Cleaner (object):
"""Tool to clean up test output to make diff-ing runs useful.
isWindows = sys.platform == 'win32'
We care about whether tests pass or fail - if that changes,
something that matters has happened - and we care about some
changes to what they say when they do fail; but we don't care
exactly what line of what file the failing line of code now
occupies, nor do we care how many milliseconds each test took to
run; and changes to the Qt version number mean nothing to us.
replacements = [
(qtver, r'@INSERT_QT_VERSION_HERE@'),
(r'Config: Using QtTest library.*', r'Config: Using QtTest library'), # Build string in text logs
(rootPath.encode('unicode-escape').decode('utf-8'), r''),
(r'( *)<Duration msecs="[\d\.]+"/>', r'\1<Duration msecs="0"/>'),
(r'( *)<QtBuild>[^<]+</QtBuild>', r'\1<QtBuild/>'), # Build element in xml, lightxml
(r'<property value="[^"]+" name="QtBuild"/>', r'<property value="" name="QtBuild"/>') # Build in xunitxml
]
Create one singleton instance; it'll do mildly expensive things
once and you can use its .clean() method to tidy up your test
output."""
extraArgs = {
"commandlinedata": "fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2",
"benchlibcallgrind": "-callgrind",
"benchlibeventcounter": "-eventcounter",
"benchliboptions": "-eventcounter",
"benchlibtickcounter": "-tickcounter",
"badxml": "-eventcounter",
"benchlibcounting": "-eventcounter",
"printdatatags": "-datatags",
"printdatatagswithglobaltags": "-datatags",
"silent": "-silent",
"verbose1": "-v1",
"verbose2": "-v2",
}
def __init__(self, here, command):
"""Set up the details we need for later cleaning.
# Replace all occurrences of searchExp in one file
def replaceInFile(file):
import sys
import fileinput
for line in fileinput.input(file, inplace=1):
for searchExp, replaceExp in replacements:
line = re.sub(searchExp, replaceExp, line)
sys.stdout.write(line)
Takes two parameters: here is $PWD and command is how this
script was invoked, from which we'll work out where it is; in
a shadow build, the former is the build tree's location
corresponding to this last. Checks $PWD does look as expected
in a build tree - raising Fail() if not - then invokes qmake
to discover Qt version (saved as .version for the benefit of
clients) and prepares the sequence of (regex, replace) pairs
that .clean() needs to do its job."""
self.version, self.__replace = self.__getPatterns(here, command)
def subdirs():
result = []
for path in os.listdir('.'):
if os.path.isdir('./' + path):
result.append(path)
return result
import re
@staticmethod
def __getPatterns(here, command,
patterns = (
# Timings:
(r'( *<Duration msecs=)"[\d\.]+"/>', r'\1"0"/>'), # xml, lightxml
(r'(Totals:.*,) *[0-9.]+ms', r'\1 0ms'), # txt
# Benchmarks:
(r'[0-9,.]+( (?:CPU ticks|msecs) per iteration \(total:) [0-9,.]+ ', r'0\1 0, '), # txt
(r'(,"(?:CPUTicks|WalltimeMilliseconds)"),\d+,\d+,', r'\1,0,0,'), # csv
(r'(<BenchmarkResult metric="(?:CPUTicks|WalltimeMilliseconds)".*\bvalue=)"[^"]+"', r'\1"0"'), # xml, lightxml
# Build details:
(r'(Config: Using QtTest library).*', r'\1'), # txt
(r'( *<QtBuild)>[^<]+</QtBuild>', r'\1/>'), # xml, lightxml
(r'(<property value=")[^"]+(" name="QtBuild"/>)', r'\1\2'), # xunitxml
# Line numbers in source files:
(r'(Loc: \[[^[\]()]+)\(\d+\)', r'\1(0)'), # txt
# (r'(\[Loc: [^[\]()]+)\(\d+\)', r'\1(0)'), # teamcity
(r'(<Incident.*\bfile=.*\bline=)"\d+"', r'\1"0"'), # lightxml, xml
),
precook = re.compile):
"""Private implementation details of __init__()."""
def getTestForPath(path):
if isWindows:
testpath = path + '\\' + path + '.exe'
else:
testpath = path + '/' + path
return testpath
qmake = ('..',) * 4 + ('bin', 'qmake')
qmake = os.path.join(*qmake)
def generateTestData(testname):
print(" running " + testname)
if os.path.sep in command:
scriptPath = os.path.abspath(command)
elif os.path.exists(command):
# e.g. if you typed "python3 generate_expected_output.py"
scriptPath = os.path.join(here, command)
else:
# From py 3.2: could use os.get_exec_path() here.
for d in os.environ.get('PATH', '').split(os.pathsep):
scriptPath = os.path.join(d, command)
if os.path.isfile(scriptPath):
break
else: # didn't break
raise Fail('Unable to find', command, 'in $PATH')
# Are we being run from the right place ?
myNames = scriptPath.split(os.path.sep)
if not (here.split(os.path.sep)[-5:] == myNames[-6:-1]
and os.path.isfile(qmake)):
raise Fail('Run', myNames[-1], 'in its directory of a completed build')
try:
qtver = subprocess.check_output([qmake, '-query', 'QT_VERSION'])
except OSError as what:
raise Fail(what.strerror)
qtver = qtver.strip().decode('utf-8')
scriptPath = os.path.dirname(scriptPath) # ditch leaf file-name
sentinel = os.path.sep + 'qtbase' + os.path.sep # '/qtbase/'
# Identify the path prefix of our qtbase ancestor directory
# (source, build and $PWD, when different); trim such prefixes
# off all paths we see.
roots = tuple(r[:r.find(sentinel) + 1].encode('unicode-escape').decode('utf-8')
for r in set((here, scriptPath, os.environ.get('PWD', '')))
if sentinel in r)
patterns += tuple((root, r'') for root in roots) + (
(r'\.'.join(qtver.split('.')), r'@INSERT_QT_VERSION_HERE@'),)
if any('-' in r for r in roots):
# Our xml formats replace hyphens with a character entity:
patterns += tuple((root.replace('-', '&#x0*2D;'), r'')
for root in roots if '-' in root)
return qtver, tuple((precook(p), r) for p, r in patterns)
del re
def clean(self, data):
"""Remove volatile details from test output.
Takes the full test output as a single (possibly huge)
multi-line string; iterates over cleaned lines of output."""
for line in data.split('\n'):
# Replace all occurrences of each regex:
for searchRe, replaceExp in self.__replace:
line = searchRe.sub(replaceExp, line)
yield line
def generateTestData(testname, clean,
formats = ('xml', 'csv', 'txt', 'xunitxml', 'lightxml'), # +'teamcity' in 5.7
extraArgs = {
"commandlinedata": "fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2",
"benchlibcallgrind": "-callgrind",
"benchlibeventcounter": "-eventcounter",
"benchliboptions": "-eventcounter",
"benchlibtickcounter": "-tickcounter",
"badxml": "-eventcounter",
"benchlibcounting": "-eventcounter",
"printdatatags": "-datatags",
"printdatatagswithglobaltags": "-datatags",
"silent": "-silent",
"verbose1": "-v1",
"verbose2": "-v2",
}):
"""Run one test and save its cleaned results.
Required arguments are the name of the test directory (the binary
it contains is expected to have the same name) and a function
that'll clean a test-run's output; see Cleaner.clean().
"""
# MS-Win: shall need to add .exe to this
path = os.path.join(testname, testname)
if not os.path.isfile(path):
print("Warning: directory", testname, "contains no test executable")
return
print(" running", testname)
for format in formats:
cmd = [getTestForPath(testname) + ' -' + format + ' ' + extraArgs.get(testname, '')]
result = 'expected_' + testname + '.' + format
data = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True).communicate()[0]
out = open(result, 'w')
out.write(data)
out.close()
replaceInFile(result)
cmd = [path, '-' + format]
if testname in extraArgs:
cmd += extraArgs[testname].split()
if isWindows:
print("This script does not work on Windows.")
exit()
data = subprocess.Popen(cmd, stdout=subprocess.PIPE,
universal_newlines=True).communicate()[0]
with open('expected_' + testname + '.' + format, 'w') as out:
out.write('\n'.join(clean(data))) # write() appends a newline, too
tests = sys.argv[1:]
os.environ['LC_ALL'] = 'C'
if len(tests) == 0:
tests = subdirs()
print("Generating " + str(len(tests)) + " test results for: " + qtver + " in: " + rootPath)
for path in tests:
if os.path.isfile(getTestForPath(path)):
generateTestData(path)
else:
print("Warning: directory " + path + " contains no test executable")
def main(name, *args):
"""Minimal argument parsing and driver for the real work"""
os.environ['LC_ALL'] = 'C'
herePath = os.getcwd()
cleaner = Cleaner(herePath, name)
tests = args if args else [d for d in os.listdir('.') if os.path.isdir(d)]
print("Generating", len(tests), "test results for", cleaner.version, "in:", herePath)
for path in tests:
generateTestData(path, cleaner.clean)
if __name__ == '__main__':
# Executed when script is run, not when imported (e.g. to debug)
import sys
if sys.platform.startswith('win'):
print("This script does not work on Windows.")
exit()
try:
main(*sys.argv)
except Fail as what:
sys.stderr.write('Failed: ' + ' '.join(what.args) + '\n')
exit(1)

View File

@ -143,6 +143,8 @@ private slots:
void positiveSign();
void interpretOnLosingFocus();
void setGroupSeparatorShown_data();
void setGroupSeparatorShown();
@ -1150,6 +1152,33 @@ void tst_QSpinBox::positiveSign()
QCOMPARE(spinBox.text(), QLatin1String("+20"));
}
void tst_QSpinBox::interpretOnLosingFocus()
{
// QTBUG-55249: When typing an invalid value after QSpinBox::clear(),
// it should be fixed up on losing focus.
static const int minimumValue = 10;
static const int maximumValue = 20;
QWidget widget;
widget.setWindowTitle(QTest::currentTestFunction());
QVBoxLayout *layout = new QVBoxLayout(&widget);
QLineEdit *focusDummy = new QLineEdit("focusDummy", &widget);
layout->addWidget(focusDummy);
SpinBox *spinBox = new SpinBox(&widget);
spinBox->setRange(minimumValue, maximumValue);
spinBox->setValue(minimumValue);
layout->addWidget(spinBox);
spinBox->clear();
spinBox->setFocus();
widget.show();
QVERIFY(QTest::qWaitForWindowActive(&widget));
QTest::keyClick(spinBox, Qt::Key_1); // Too small
focusDummy->setFocus();
QCOMPARE(spinBox->value(), minimumValue);
QCOMPARE(spinBox->lineEdit()->text().toInt(), minimumValue);
}
void tst_QSpinBox::setGroupSeparatorShown_data()
{
QTest::addColumn<QLocale::Language>("lang");

View File

@ -37,26 +37,22 @@
#include <QOpenGLFunctions>
#include <QPainter>
#include <QElapsedTimer>
#include <QCommandLineParser>
#include <QScreen>
const char applicationDescription[] = "\n\
This application opens multiple windows and continuously schedules updates for\n\
them. Each of them is a separate QOpenGLWindow so there will be a separate\n\
context and swapBuffers call for each.\n\
\n\
By default the swap interval is 1 so the effect of multiple blocking swapBuffers\n\
on the main thread can be examined. (the result is likely to be different\n\
between platforms, for example OS X is buffer queuing meaning that it can\n\
block outside swap, resulting in perfect vsync for all three windows, while\n\
other systems that block on swap will kill the frame rate due to blocking the\n\
thread three times)\
";
// This application opens three windows and continuously schedules updates for
// them. Each of them is a separate QOpenGLWindow so there will be a separate
// context and swapBuffers call for each.
//
// By default the swap interval is 1 so the effect of three blocking swapBuffers
// on the main thread can be examined. (the result is likely to be different
// between platforms, for example OS X is buffer queuing meaning that it can
// block outside swap, resulting in perfect vsync for all three windows, while
// other systems that block on swap will kill the frame rate due to blocking the
// thread three times)
//
// Pass --novsync to set a swap interval of 0. This should give an unthrottled
// refresh on all platforms for all three windows.
//
// Passing --vsyncone sets swap interval to 1 for the first window and 0 to the
// others.
//
// Pass --extrawindows N to open N windows in addition to the default 3.
//
// For reference, below is a table of some test results.
//
// swap interval 1 for all swap interval 1 for only one and 0 for others
@ -69,12 +65,15 @@
class Window : public QOpenGLWindow
{
Q_OBJECT
public:
Window(int n) : idx(n) {
r = g = b = fps = 0;
y = 0;
resize(200, 200);
t2.start();
connect(this, SIGNAL(frameSwapped()), SLOT(frameSwapped()));
fpsTimer.start();
}
void paintGL() {
@ -106,27 +105,52 @@ public:
if (y > height() - 20)
y = 20;
if (t2.elapsed() > 1000) {
fps = 1000.0 / t.elapsed();
t2.restart();
}
t.restart();
update();
}
public slots:
void frameSwapped() {
++framesSwapped;
if (fpsTimer.elapsed() > 1000) {
fps = qRound(framesSwapped * (1000.0 / fpsTimer.elapsed()));
framesSwapped = 0;
fpsTimer.restart();
}
}
private:
int idx;
GLfloat r, g, b, fps;
GLfloat r, g, b;
int y;
QElapsedTimer t, t2;
int framesSwapped;
QElapsedTimer fpsTimer;
int fps;
};
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
QCommandLineParser parser;
parser.setApplicationDescription(applicationDescription);
parser.addHelpOption();
QCommandLineOption noVsyncOption("novsync", "Disable Vsync by setting swap interval to 0. "
"This should give an unthrottled refresh on all platforms for all windows.");
parser.addOption(noVsyncOption);
QCommandLineOption vsyncOneOption("vsyncone", "Enable Vsync only for first window, "
"by setting swap interval to 1 for the first window and 0 for the others.");
parser.addOption(vsyncOneOption);
QCommandLineOption numWindowsOption("numwindows", "Open <N> windows instead of the default 3.", "N", "3");
parser.addOption(numWindowsOption);
parser.process(app);
QSurfaceFormat fmt;
if (QGuiApplication::arguments().contains(QLatin1String("--novsync"))) {
if (parser.isSet(noVsyncOption)) {
qDebug("swap interval 0 (no throttling)");
fmt.setSwapInterval(0);
} else {
@ -134,36 +158,41 @@ int main(int argc, char **argv)
}
QSurfaceFormat::setDefaultFormat(fmt);
Window w1(0);
if (QGuiApplication::arguments().contains(QLatin1String("--vsyncone"))) {
qDebug("swap interval 1 for first window only");
QSurfaceFormat w1fmt = fmt;
w1fmt.setSwapInterval(1);
w1.setFormat(w1fmt);
fmt.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(fmt);
}
Window w2(1);
Window w3(2);
w1.setGeometry(QRect(QPoint(10, 100), w1.size()));
w2.setGeometry(QRect(QPoint(300, 100), w2.size()));
w3.setGeometry(QRect(QPoint(600, 100), w3.size()));
w1.show();
w2.show();
w3.show();
QRect availableGeometry = app.primaryScreen()->availableGeometry();
QList<QWindow *> extraWindows;
int countIdx;
if ((countIdx = QGuiApplication::arguments().indexOf(QLatin1String("--extrawindows"))) >= 0) {
int extraWindowCount = QGuiApplication::arguments().at(countIdx + 1).toInt();
for (int i = 0; i < extraWindowCount; ++i) {
Window *w = new Window(3 + i);
extraWindows << w;
w->show();
int numberOfWindows = qMax(parser.value(numWindowsOption).toInt(), 1);
QList<QWindow *> windows;
for (int i = 0; i < numberOfWindows; ++i) {
Window *w = new Window(i + 1);
windows << w;
if (i == 0 && parser.isSet(vsyncOneOption)) {
qDebug("swap interval 1 for first window only");
QSurfaceFormat vsyncedSurfaceFormat = fmt;
vsyncedSurfaceFormat.setSwapInterval(1);
w->setFormat(vsyncedSurfaceFormat);
fmt.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(fmt);
}
static int windowWidth = w->width() + 20;
static int windowHeight = w->height() + 20;
static int windowsPerRow = availableGeometry.width() / windowWidth;
int col = i;
int row = col / windowsPerRow;
col -= row * windowsPerRow;
QPoint position = availableGeometry.topLeft();
position += QPoint(col * windowWidth, row * windowHeight);
w->setFramePosition(position);
w->show();
}
int r = app.exec();
qDeleteAll(extraWindows);
qDeleteAll(windows);
return r;
}
#include "main.moc"