summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/global/manifest-meta.qdocconf27
-rw-r--r--doc/global/qt-cpp-defines.qdocconf1
-rw-r--r--examples/widgets/animation/stickman/graphicsview.h2
-rw-r--r--src/concurrent/doc/src/qtconcurrent-index.qdoc4
-rw-r--r--src/concurrent/qtconcurrentfilter.cpp2
-rw-r--r--src/concurrent/qtconcurrentmap.cpp6
-rw-r--r--src/concurrent/qtconcurrentrun.cpp2
-rw-r--r--src/corelib/doc/src/threads.qdoc108
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp21
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify_p.h5
-rw-r--r--src/corelib/io/qprocess_unix.cpp40
-rw-r--r--src/corelib/thread/qfuture.qdoc5
-rw-r--r--src/corelib/thread/qfuturesynchronizer.qdoc2
-rw-r--r--src/corelib/thread/qfuturewatcher.cpp2
-rw-r--r--src/gui/image/qpnghandler.cpp24
-rw-r--r--src/gui/painting/qtransform.cpp27
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp2
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp4
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp4
-rw-r--r--src/plugins/accessible/widgets/main.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm8
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp145
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.h9
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp4
-rw-r--r--src/printsupport/dialogs/qprintdialog_mac.mm2
-rw-r--r--src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp4
-rw-r--r--tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp81
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp2
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp45
31 files changed, 429 insertions, 169 deletions
diff --git a/doc/global/manifest-meta.qdocconf b/doc/global/manifest-meta.qdocconf
index 6b55e0dbad..20419f1b29 100644
--- a/doc/global/manifest-meta.qdocconf
+++ b/doc/global/manifest-meta.qdocconf
@@ -32,7 +32,7 @@
# manifestmeta.global.names = *
# manifestmeta.global.tags = qt5
-manifestmeta.filters = highlighted webkit1 webkit2 android
+manifestmeta.filters = highlighted webkit1 webkit2 android thumbnail
manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \
"QtQuick/Qt Quick Demo - Photo Surface" \
@@ -168,3 +168,28 @@ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \
"QtWidgets/Address Book Example"
manifestmeta.android.tags = android
+
+# add a generic thumbnail image to examples that do not have any images in their documentation
+manifestmeta.thumbnail.attributes = "imageUrl:qthelp\://org.qt-project.qtdoc.$QT_VERSION_TAG/qtdoc/images/qt-codesample.png"
+
+manifestmeta.thumbnail.names = "QtConcurrent/Map Example" \
+ "QtConcurrent/QtConcurrent Word Count Example" \
+ "QtConcurrent/Run Function Example" \
+ "QtGui/Raster Window Example" \
+ "QtNetwork/Network Download*" \
+ "QtWidgets/Dynamic Layouts Example" \
+ "QtWidgets/Event Transitions Example" \
+ "QtWidgets/Plug & Paint Basic Tools Example" \
+ "QtWidgets/Plug & Paint Extra Filters Example" \
+ "QtWidgets/Two-way Button Example" \
+ "QtWidgets/Validators Example" \
+ "ActiveQt/*" \
+ "QtDbus/*" \
+ "QtHelp/*" \
+ "QtMultimedia/AudioEngine Example" \
+ "QtMultimedia/Declarative Radio Example" \
+ "QtMultimedia/Media Player Example" \
+ "QtQml/Extending QML*" \
+ "QtQuick/Qt Quick Examples - Accessibility" \
+ "QtSensors/Qt Sensors - SensorGesture QML Type example" \
+ "QtWinExtras/Icon Extractor"
diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf
index 6966e2c4c1..406e37af08 100644
--- a/doc/global/qt-cpp-defines.qdocconf
+++ b/doc/global/qt-cpp-defines.qdocconf
@@ -26,6 +26,7 @@ Cpp.ignoretokens += \
Q_CORE_EXPORT_INLINE \
Q_DBUS_EXPORT \
Q_DECL_CONSTEXPR \
+ Q_DECL_DEPRECATED \
Q_DECL_NOEXCEPT \
Q_DECL_NOTHROW \
Q_DECLARATIVE_EXPORT \
diff --git a/examples/widgets/animation/stickman/graphicsview.h b/examples/widgets/animation/stickman/graphicsview.h
index 8042a65897..60abb6448f 100644
--- a/examples/widgets/animation/stickman/graphicsview.h
+++ b/examples/widgets/animation/stickman/graphicsview.h
@@ -39,7 +39,7 @@
****************************************************************************/
#ifndef GRAPHICSVIEW_H
-#define GRAPHICSVIEW
+#define GRAPHICSVIEW_H
#include <QtWidgets/QGraphicsView>
diff --git a/src/concurrent/doc/src/qtconcurrent-index.qdoc b/src/concurrent/doc/src/qtconcurrent-index.qdoc
index c884b0da07..d259516119 100644
--- a/src/concurrent/doc/src/qtconcurrent-index.qdoc
+++ b/src/concurrent/doc/src/qtconcurrent-index.qdoc
@@ -117,8 +117,8 @@
Random access iterators can be faster in cases where Qt Concurrent is iterating
over a large number of lightweight items, since they allow skipping to any point
in the container. In addition, using random access iterators allows Qt Concurrent
- to provide progress information trough QFuture::progressValue() and QFutureWatcher::
- progressValueChanged().
+ to provide progress information trough QFuture::progressValue() and
+ QFutureWatcher::progressValueChanged().
The non in-place modifying functions such as mapped() and filtered() makes a
copy of the container when called. If you are using STL containers this copy operation
diff --git a/src/concurrent/qtconcurrentfilter.cpp b/src/concurrent/qtconcurrentfilter.cpp
index ef0229a695..7889fbff56 100644
--- a/src/concurrent/qtconcurrentfilter.cpp
+++ b/src/concurrent/qtconcurrentfilter.cpp
@@ -47,7 +47,7 @@
\brief The <QtConcurrentFilter> header provides concurrent Filter and
Filter-Reduce.
- These functions are a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+ These functions are a part of the \l {Qt Concurrent} framework.
The QtConcurrent::filter(), QtConcurrent::filtered() and
QtConcurrent::filteredReduced() functions filter items in a sequence such
diff --git a/src/concurrent/qtconcurrentmap.cpp b/src/concurrent/qtconcurrentmap.cpp
index 9718baf48f..da2a601ae2 100644
--- a/src/concurrent/qtconcurrentmap.cpp
+++ b/src/concurrent/qtconcurrentmap.cpp
@@ -47,8 +47,8 @@
possible to write multi-threaded programs without using low-level
threading primitives.
- See the \l {Concurrent Programming}{Qt Concurrent} chapter in
- the \l{threads.html}{threading} documentation.
+ See the \l {Qt Concurrent} module documentation for an overview of available
+ functions, or see below for detailed information on each function.
\inheaderfile QtConcurrent
\ingroup thread
@@ -74,7 +74,7 @@
\brief The <QtConcurrentMap> header provides concurrent Map and MapReduce.
- These functions are a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+ These functions are a part of the \l {Qt Concurrent} framework.
The QtConcurrent::map(), QtConcurrent::mapped() and
QtConcurrent::mappedReduced() functions run computations in parallel on
diff --git a/src/concurrent/qtconcurrentrun.cpp b/src/concurrent/qtconcurrentrun.cpp
index 4ab1399c0c..4398e1a91f 100644
--- a/src/concurrent/qtconcurrentrun.cpp
+++ b/src/concurrent/qtconcurrentrun.cpp
@@ -48,7 +48,7 @@
\ingroup thread
- This function is a part of the \l {Concurrent Programming}{Qt Concurrent} framework.
+ This function is a part of the \l {Qt Concurrent} framework.
The QtConcurrent::run() function runs a function in a separate thread.
The return value of the function is made available through the QFuture API.
diff --git a/src/corelib/doc/src/threads.qdoc b/src/corelib/doc/src/threads.qdoc
index 9b80f0d200..c250f7466b 100644
--- a/src/corelib/doc/src/threads.qdoc
+++ b/src/corelib/doc/src/threads.qdoc
@@ -63,7 +63,6 @@
\li \l{Synchronizing Threads}
\li \l{Reentrancy and Thread-Safety}
\li \l{Threads and QObjects}
- \li \l{Concurrent Programming}
\li \l{Thread-Support in Qt Modules}
\endlist
@@ -449,7 +448,7 @@
\previouspage Reentrancy and Thread Safety
\contentspage Thread Support in Qt
- \nextpage Concurrent Programming
+ \nextpage Thread-Support in Qt Modules
QThread inherits QObject. It emits signals to indicate that the
thread started or finished executing, and provides a few slots as
@@ -646,113 +645,10 @@
*/
/*!
- \page threads-qtconcurrent.html
- \title Concurrent Programming
-
- \previouspage Threads and QObjects
- \contentspage Thread Support in Qt
- \nextpage Thread-Support in Qt Modules
-
- \target qtconcurrent intro
-
- The QtConcurrent namespace provides high-level APIs that make it
- possible to write multi-threaded programs without using low-level
- threading primitives such as mutexes, read-write locks, wait
- conditions, or semaphores. Programs written with QtConcurrent
- automatically adjust the number of threads used according to the
- number of processor cores available. This means that applications
- written today will continue to scale when deployed on multi-core
- systems in the future.
-
- QtConcurrent includes functional programming style APIs for
- parallel list processing, including a MapReduce and FilterReduce
- implementation for shared-memory (non-distributed) systems, and
- classes for managing asynchronous computations in GUI
- applications:
-
- \list
-
- \li QtConcurrent::map() applies a function to every item in a container,
- modifying the items in-place.
-
- \li QtConcurrent::mapped() is like map(), except that it returns a new
- container with the modifications.
-
- \li QtConcurrent::mappedReduced() is like mapped(), except that the
- modified results are reduced or folded into a single result.
-
- \li QtConcurrent::filter() removes all items from a container based on the
- result of a filter function.
-
- \li QtConcurrent::filtered() is like filter(), except that it returns a new
- container with the filtered results.
-
- \li QtConcurrent::filteredReduced() is like filtered(), except that the
- filtered results are reduced or folded into a single result.
-
- \li QtConcurrent::run() runs a function in another thread.
-
- \li QFuture represents the result of an asynchronous computation.
-
- \li QFutureIterator allows iterating through results available via QFuture.
-
- \li QFutureWatcher allows monitoring a QFuture using signals-and-slots.
-
- \li QFutureSynchronizer is a convenience class that automatically
- synchronizes several QFutures.
-
- \endlist
-
- Qt Concurrent supports several STL-compatible container and iterator types,
- but works best with Qt containers that have random-access iterators, such as
- QList or QVector. The map and filter functions accept both containers and begin/end iterators.
-
- STL Iterator support overview:
-
- \table
- \header
- \li Iterator Type
- \li Example classes
- \li Support status
- \row
- \li Input Iterator
- \li
- \li Not Supported
- \row
- \li Output Iterator
- \li
- \li Not Supported
- \row
- \li Forward Iterator
- \li std::slist
- \li Supported
- \row
- \li Bidirectional Iterator
- \li QLinkedList, std::list
- \li Supported
- \row
- \li Random Access Iterator
- \li QList, QVector, std::vector
- \li Supported and Recommended
- \endtable
-
- Random access iterators can be faster in cases where Qt Concurrent is iterating
- over a large number of lightweight items, since they allow skipping to any point
- in the container. In addition, using random access iterators allows Qt Concurrent
- to provide progress information trough QFuture::progressValue() and QFutureWatcher::
- progressValueChanged().
-
- The non in-place modifying functions such as mapped() and filtered() makes a
- copy of the container when called. If you are using STL containers this copy operation
- might take some time, in this case we recommend specifying the begin and end iterators
- for the container instead.
-*/
-
-/*!
\page threads-modules.html
\title Thread-Support in Qt Modules
- \previouspage Concurrent Programming
+ \previouspage Threads and QObjects
\contentspage Thread Support in Qt
\section1 Threads and the SQL Module
diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp
index 024af79c33..c731f3d417 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp
@@ -365,11 +365,11 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
// qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask;
int id = event.wd;
- QString path = idToPath.value(id);
+ QString path = getPathFromID(id);
if (path.isEmpty()) {
// perhaps a directory?
id = -id;
- path = idToPath.value(id);
+ path = getPathFromID(id);
if (path.isEmpty())
continue;
}
@@ -378,8 +378,9 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) {
pathToID.remove(path);
- idToPath.remove(id);
- inotify_rm_watch(inotifyFd, event.wd);
+ idToPath.remove(id, getPathFromID(id));
+ if (!idToPath.contains(id))
+ inotify_rm_watch(inotifyFd, event.wd);
if (id < 0)
emit directoryChanged(path, true);
@@ -394,6 +395,18 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
}
}
+QString QInotifyFileSystemWatcherEngine::getPathFromID(int id) const
+{
+ QHash<int, QString>::const_iterator i = idToPath.find(id);
+ while (i != idToPath.constEnd() && i.key() == id) {
+ if ((i + 1) == idToPath.constEnd() || (i + 1).key() != id) {
+ return i.value();
+ }
+ ++i;
+ }
+ return QString();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_FILESYSTEMWATCHER
diff --git a/src/corelib/io/qfilesystemwatcher_inotify_p.h b/src/corelib/io/qfilesystemwatcher_inotify_p.h
index 959d9edc12..d02f04eed6 100644
--- a/src/corelib/io/qfilesystemwatcher_inotify_p.h
+++ b/src/corelib/io/qfilesystemwatcher_inotify_p.h
@@ -79,10 +79,13 @@ private Q_SLOTS:
void readFromInotify();
private:
+ QString getPathFromID(int id) const;
+
+private:
QInotifyFileSystemWatcherEngine(int fd, QObject *parent);
int inotifyFd;
QHash<QString, int> pathToID;
- QHash<int, QString> idToPath;
+ QMultiHash<int, QString> idToPath;
QSocketNotifier notifier;
};
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 9868ea624a..eab3890beb 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -121,17 +121,33 @@ static const int errorBufferMax = 512;
static int qt_qprocess_deadChild_pipe[2];
static struct sigaction qt_sa_old_sigchld_handler;
-static void qt_sa_sigchld_handler(int signum)
+static void qt_sa_sigchld_sigaction(int signum, siginfo_t *info, void *context)
{
+ // *Never* use the info or contect variables in this function
+ // (except for passing them to the next signal in the chain).
+ // We cannot be sure if another library or if the application
+ // installed a signal handler for SIGCHLD without SA_SIGINFO
+ // and fails to pass the arguments to us. If they do that,
+ // these arguments contain garbage and we'd most likely crash.
+
qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
#if defined (QPROCESS_DEBUG)
fprintf(stderr, "*** SIGCHLD\n");
#endif
- // load it as volatile
- void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler;
- if (oldAction && oldAction != SIG_IGN)
- oldAction(signum);
+ // load as volatile
+ volatile struct sigaction *vsa = &qt_sa_old_sigchld_handler;
+
+ if (qt_sa_old_sigchld_handler.sa_flags & SA_SIGINFO) {
+ void (*oldAction)(int, siginfo_t *, void *) = vsa->sa_sigaction;
+
+ oldAction(signum, info, context);
+ } else {
+ void (*oldAction)(int) = vsa->sa_handler;
+
+ if (oldAction && oldAction != SIG_IGN)
+ oldAction(signum);
+ }
}
static inline void add_fd(int &nfds, int fd, fd_set *fdset)
@@ -197,10 +213,16 @@ QProcessManager::QProcessManager()
// set up the SIGCHLD handler, which writes a single byte to the dead
// child pipe every time a child dies.
+
struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = qt_sa_sigchld_handler;
- action.sa_flags = SA_NOCLDSTOP;
+ // use the old handler as template, i.e., preserve the signal mask
+ // otherwise the original signal handler might be interrupted although it
+ // was marked to never be interrupted
+ ::sigaction(SIGCHLD, NULL, &action);
+ action.sa_sigaction = qt_sa_sigchld_sigaction;
+ // set the SA_SIGINFO flag such that we can use the three argument handler
+ // function
+ action.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler);
processManagerInstance = this;
@@ -225,7 +247,7 @@ QProcessManager::~QProcessManager()
struct sigaction currentAction;
::sigaction(SIGCHLD, 0, &currentAction);
- if (currentAction.sa_handler == qt_sa_sigchld_handler) {
+ if (currentAction.sa_sigaction == qt_sa_sigchld_sigaction) {
::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
}
diff --git a/src/corelib/thread/qfuture.qdoc b/src/corelib/thread/qfuture.qdoc
index 421e683c4a..7ae3e4a87e 100644
--- a/src/corelib/thread/qfuture.qdoc
+++ b/src/corelib/thread/qfuture.qdoc
@@ -47,8 +47,7 @@
\ingroup thread
- To start a computation, use one of the APIs in the
- \l {Concurrent Programming}{Qt Concurrent} framework.
+ To start a computation, use one of the APIs in the \l {Qt Concurrent} framework.
QFuture allows threads to be synchronized against one or more results
which will be ready at a later point in time. The result can be of any type
@@ -93,7 +92,7 @@
To interact with running tasks using signals and slots, use QFutureWatcher.
- \sa QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+ \sa QFutureWatcher, {Qt Concurrent}
*/
/*! \fn QFuture::QFuture()
diff --git a/src/corelib/thread/qfuturesynchronizer.qdoc b/src/corelib/thread/qfuturesynchronizer.qdoc
index 7ad978f61d..cc31dff46d 100644
--- a/src/corelib/thread/qfuturesynchronizer.qdoc
+++ b/src/corelib/thread/qfuturesynchronizer.qdoc
@@ -66,7 +66,7 @@
You can query the status of the cancel-on-wait feature using the
cancelOnWait() function.
- \sa QFuture, QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
+ \sa QFuture, QFutureWatcher, {Qt Concurrent}
*/
/*!
diff --git a/src/corelib/thread/qfuturewatcher.cpp b/src/corelib/thread/qfuturewatcher.cpp
index 53a00a8212..a7f2dd9f73 100644
--- a/src/corelib/thread/qfuturewatcher.cpp
+++ b/src/corelib/thread/qfuturewatcher.cpp
@@ -98,7 +98,7 @@ QT_BEGIN_NAMESPACE
QFutureWatcher<void> as well. This is useful if only status or progress
information is needed; not the actual result data.
- \sa QFuture, {Concurrent Programming}{Qt Concurrent}
+ \sa QFuture, {Qt Concurrent}
*/
/*! \fn QFutureWatcher::QFutureWatcher(QObject *parent)
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 7838b7df8e..3ee9e200de 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@@ -280,6 +281,15 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scal
image.setColorCount(2);
image.setColor(1, qRgb(0,0,0));
image.setColor(0, qRgb(255,255,255));
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
+ const int g = trans_color_p->gray;
+ // the image has white in the first position of the color table,
+ // black in the second. g is 0 for black, 1 for white.
+ if (g == 0)
+ image.setColor(1, qRgba(0, 0, 0, 0));
+ else if (g == 1)
+ image.setColor(0, qRgba(255, 255, 255, 0));
+ }
} else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_expand(png_ptr);
png_set_strip_16(png_ptr);
@@ -406,14 +416,14 @@ static void read_image_scaled(QImage *outImage, png_structp png_ptr, png_infop i
QPngHandlerPrivate::AllocatedMemoryPointers &amp, QSize scaledSize)
{
- png_uint_32 width;
- png_uint_32 height;
- png_int_32 offset_x;
- png_int_32 offset_y;
+ png_uint_32 width = 0;
+ png_uint_32 height = 0;
+ png_int_32 offset_x = 0;
+ png_int_32 offset_y = 0;
- int bit_depth;
- int color_type;
- int unit_type;
+ int bit_depth = 0;
+ int color_type = 0;
+ int unit_type = PNG_OFFSET_PIXEL;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);
uchar *data = outImage->bits();
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 5088e9cdc8..a07b5def5d 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -2293,13 +2293,30 @@ bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
return qFuzzyCompare(xScale, yScale);
}
- const qreal xScale = transform.m11() * transform.m11()
+ // rotate then scale: compare columns
+ const qreal xScale1 = transform.m11() * transform.m11()
+ transform.m21() * transform.m21();
- const qreal yScale = transform.m12() * transform.m12()
+ const qreal yScale1 = transform.m12() * transform.m12()
+ transform.m22() * transform.m22();
- if (scale)
- *scale = qSqrt(qMax(xScale, yScale));
- return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale);
+
+ // scale then rotate: compare rows
+ const qreal xScale2 = transform.m11() * transform.m11()
+ + transform.m12() * transform.m12();
+ const qreal yScale2 = transform.m21() * transform.m21()
+ + transform.m22() * transform.m22();
+
+ // decide the order of rotate and scale operations
+ if (qAbs(xScale1 - yScale1) > qAbs(xScale2 - yScale2)) {
+ if (scale)
+ *scale = qSqrt(qMax(xScale1, yScale1));
+
+ return type == QTransform::TxRotate && qFuzzyCompare(xScale1, yScale1);
+ } else {
+ if (scale)
+ *scale = qSqrt(qMax(xScale2, yScale2));
+
+ return type == QTransform::TxRotate && qFuzzyCompare(xScale2, yScale2);
+ }
}
QT_END_NAMESPACE
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index c3e3716b26..b6a3b5e3ab 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -509,7 +509,7 @@ void QHttpNetworkConnectionPrivate::createAuthorization(QAbstractSocket *socket,
// Send "Authorization" header, but not if it's NTLM and the socket is already authenticated.
if (channels[i].authMethod != QAuthenticatorPrivate::None) {
- if (!(channels[i].authMethod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 401)) {
+ if ((channels[i].authMethod != QAuthenticatorPrivate::Ntlm && request.headerField("Authorization").isEmpty()) || channels[i].lastStatus == 401) {
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[i].authenticator);
if (priv && priv->method != QAuthenticatorPrivate::None) {
QByteArray response = priv->calculateResponse(request.d->methodName(), request.d->uri(false));
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 6e61eea5a4..da82fdf8d2 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -236,8 +236,8 @@ bool QHttpNetworkConnectionChannel::sendRequest()
QAuthenticator &auth = authenticator;
if (url.userName() != auth.user()
|| (!url.password().isEmpty() && url.password() != auth.password())) {
- auth.setUser(url.userName());
- auth.setPassword(url.password());
+ auth.setUser(url.userName(QUrl::FullyDecoded));
+ auth.setPassword(url.password(QUrl::FullyDecoded));
connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false);
}
// clear the userinfo, since we use the same request for resending
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 91655ef485..101e1a8c25 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1358,8 +1358,8 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen
// if credentials are included in the url, then use them
if (!url.userName().isEmpty()
&& !url.password().isEmpty()) {
- authenticator->setUser(url.userName());
- authenticator->setPassword(url.password());
+ authenticator->setUser(url.userName(QUrl::FullyDecoded));
+ authenticator->setPassword(url.password(QUrl::FullyDecoded));
*urlForLastAuthentication = url;
authenticationManager->cacheCredentials(url, authenticator);
return;
diff --git a/src/plugins/accessible/widgets/main.cpp b/src/plugins/accessible/widgets/main.cpp
index 686a90ca96..36ee784aac 100644
--- a/src/plugins/accessible/widgets/main.cpp
+++ b/src/plugins/accessible/widgets/main.cpp
@@ -115,7 +115,7 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
QToolButton *tb = qobject_cast<QToolButton*>(widget);
if (!tb->menu())
role = tb->isCheckable() ? QAccessible::CheckBox : QAccessible::PushButton;
- else if (!tb->popupMode() != QToolButton::DelayedPopup)
+ else if (tb->popupMode() == QToolButton::DelayedPopup)
role = QAccessible::ButtonDropDown;
else
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 7831888da1..8620ef4267 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -125,7 +125,7 @@ public:
QList<int> possibleKeys(const QKeyEvent *event) const;
void updateScreens();
- QCocoaScreen *screenAtIndex(int index) const { return mScreens.at(index); }
+ QCocoaScreen *screenAtIndex(int index);
private:
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 6d1882f622..365fa92470 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -343,6 +343,14 @@ void QCocoaIntegration::updateScreens()
screen->setVirtualSiblings(siblings);
}
+QCocoaScreen *QCocoaIntegration::screenAtIndex(int index)
+{
+ if (index >= mScreens.count())
+ updateScreens();
+
+ return mScreens.at(index);
+}
+
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index ab48d18af4..dd292fd2a3 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -157,12 +157,122 @@ private:
QByteArray format_atoms;
};
+class INCRTransaction;
+typedef QMap<xcb_window_t,INCRTransaction*> TransactionMap;
+static TransactionMap *transactions = 0;
+
+//#define INCR_DEBUG
+
+class INCRTransaction : public QObject
+{
+ Q_OBJECT
+public:
+ INCRTransaction(QXcbConnection *c, xcb_window_t w, xcb_atom_t p,
+ QByteArray d, uint i, xcb_atom_t t, int f, int to) :
+ conn(c), win(w), property(p), data(d), increment(i),
+ target(t), format(f), timeout(to), offset(0)
+ {
+ const quint32 values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
+ xcb_change_window_attributes(conn->xcb_connection(), win,
+ XCB_CW_EVENT_MASK, values);
+ if (!transactions) {
+#ifdef INCR_DEBUG
+ qDebug("INCRTransaction: creating the TransactionMap");
+#endif
+ transactions = new TransactionMap;
+ conn->clipboard()->setProcessIncr(true);
+ }
+ transactions->insert(win, this);
+ abort_timer = startTimer(timeout);
+ }
+
+ ~INCRTransaction()
+ {
+ if (abort_timer)
+ killTimer(abort_timer);
+ abort_timer = 0;
+ transactions->remove(win);
+ if (transactions->isEmpty()) {
+#ifdef INCR_DEBUG
+ qDebug("INCRTransaction: no more INCR transactions left in the TransactionMap");
+#endif
+ delete transactions;
+ transactions = 0;
+ conn->clipboard()->setProcessIncr(false);
+ }
+ }
+
+ void updateIncrProperty(xcb_property_notify_event_t *event, bool &accepted)
+ {
+ xcb_connection_t *c = conn->xcb_connection();
+ if (event->atom == property && event->state == XCB_PROPERTY_DELETE) {
+ accepted = true;
+ // restart the timer
+ if (abort_timer)
+ killTimer(abort_timer);
+ abort_timer = startTimer(timeout);
+
+ unsigned int bytes_left = data.size() - offset;
+ if (bytes_left > 0) {
+ unsigned int bytes_to_send = qMin(increment, bytes_left);
+#ifdef INCR_DEBUG
+ qDebug("INCRTransaction: sending %d bytes, %d remaining (INCR transaction %p)",
+ bytes_to_send, bytes_left - bytes_to_send, this);
+#endif
+ int dataSize = bytes_to_send / (format / 8);
+ xcb_change_property(c, XCB_PROP_MODE_REPLACE, win, property,
+ target, format, dataSize, data.constData() + offset);
+ offset += bytes_to_send;
+ } else {
+#ifdef INCR_DEBUG
+ qDebug("INCRTransaction: INCR transaction %p completed", this);
+#endif
+ xcb_change_property(c, XCB_PROP_MODE_REPLACE, win, property,
+ target, format, 0, (const void *)0);
+ const quint32 values[] = { XCB_EVENT_MASK_NO_EVENT };
+ xcb_change_window_attributes(conn->xcb_connection(), win,
+ XCB_CW_EVENT_MASK, values);
+ // self destroy
+ delete this;
+ }
+ }
+ }
+
+protected:
+ void timerEvent(QTimerEvent *ev)
+ {
+ if (ev->timerId() == abort_timer) {
+ // this can happen when the X client we are sending data
+ // to decides to exit (normally or abnormally)
+#ifdef INCR_DEBUG
+ qDebug("INCRTransaction: Timed out while sending data to %p", this);
+#endif
+ delete this;
+ }
+ }
+
+private:
+ QXcbConnection *conn;
+ xcb_window_t win;
+ xcb_atom_t property;
+ QByteArray data;
+ uint increment;
+ xcb_atom_t target;
+ int format;
+ int timeout;
+ uint offset;
+ int abort_timer;
+};
+
const int QXcbClipboard::clipboard_timeout = 5000;
QXcbClipboard::QXcbClipboard(QXcbConnection *c)
: QXcbObject(c), QPlatformClipboard()
, m_requestor(XCB_NONE)
, m_owner(XCB_NONE)
+ , m_incr_active(false)
+ , m_clipboard_closing(false)
+ , m_incr_receive_time(0)
{
Q_ASSERT(QClipboard::Clipboard == 0);
Q_ASSERT(QClipboard::Selection == 1);
@@ -200,6 +310,7 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
QXcbClipboard::~QXcbClipboard()
{
+ m_clipboard_closing = true;
// Transfer the clipboard content to the clipboard manager if we own a selection
if (m_timestamp[QClipboard::Clipboard] != XCB_CURRENT_TIME ||
m_timestamp[QClipboard::Selection] != XCB_CURRENT_TIME) {
@@ -224,6 +335,17 @@ QXcbClipboard::~QXcbClipboard()
}
}
+void QXcbClipboard::incrTransactionPeeker(xcb_generic_event_t *ge, bool &accepted)
+{
+ uint response_type = ge->response_type & ~0x80;
+ if (response_type == XCB_PROPERTY_NOTIFY) {
+ xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge;
+ TransactionMap::Iterator it = transactions->find(event->window);
+ if (it != transactions->end()) {
+ (*it)->updateIncrProperty(event, accepted);
+ }
+ }
+}
xcb_window_t QXcbClipboard::getSelectionOwner(xcb_atom_t atom) const
{
@@ -415,16 +537,17 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
// Motif clients (since Motif doesn't support INCR)
static xcb_atom_t motif_clip_temporary = atom(QXcbAtom::CLIP_TEMPORARY);
bool allow_incr = property != motif_clip_temporary;
-
+ // This 'bool' can be removed once there is a proper fix for QTBUG-32853
+ if (m_clipboard_closing)
+ allow_incr = false;
// X_ChangeProperty protocol request is 24 bytes
const int increment = (xcb_get_maximum_request_length(xcb_connection()) * 4) - 24;
if (data.size() > increment && allow_incr) {
long bytes = data.size();
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, property,
atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
-
-// (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment);
- qWarning("QXcbClipboard: INCR is unimplemented");
+ new INCRTransaction(connection(), window, property, data, increment,
+ atomFormat, dataFormat, clipboard_timeout);
return property;
}
@@ -611,7 +734,7 @@ static inline int maxSelectionIncr(xcb_connection_t *c)
return (l > 65536 ? 65536*4 : l*4) - 100;
}
-bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format) const
+bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format)
{
int maxsize = maxSelectionIncr(xcb_connection());
ulong bytes_left; // bytes_after
@@ -687,7 +810,8 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
// correct size, not 0-term.
if (size)
*size = buffer_offset;
-
+ if (*type == atom(QXcbAtom::INCR))
+ m_incr_receive_time = connection()->getTimestamp();
if (deleteProperty)
xcb_delete_property(xcb_connection(), win, property);
@@ -791,6 +915,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
bool alloc_error = false;
int length;
int offset = 0;
+ xcb_timestamp_t prev_time = m_incr_receive_time;
if (nbytes > 0) {
// Reserve buffer + zero-terminator (for text data)
@@ -805,10 +930,14 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY, clipboard_timeout);
if (!ge)
break;
-
xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge;
- if (event->atom != property || event->state != XCB_PROPERTY_NEW_VALUE)
+
+ if (event->atom != property
+ || event->state != XCB_PROPERTY_NEW_VALUE
+ || event->time < prev_time)
continue;
+ prev_time = event->time;
+
if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) {
if (length == 0) { // no more data, we're done
if (nullterm) {
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h
index 61cdce3d1d..03021aa606 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.h
+++ b/src/plugins/platforms/xcb/qxcbclipboard.h
@@ -78,11 +78,15 @@ public:
void handleSelectionClearRequest(xcb_selection_clear_event_t *event);
void handleXFixesSelectionRequest(xcb_xfixes_selection_notify_event_t *event);
- bool clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format) const;
+ bool clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format);
QByteArray clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm);
QByteArray getDataInFormat(xcb_atom_t modeAtom, xcb_atom_t fmtatom);
+ void setProcessIncr(bool process) { m_incr_active = process; }
+ bool processIncr() { return m_incr_active; }
+ void incrTransactionPeeker(xcb_generic_event_t *ge, bool &accepted);
+
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0);
@@ -107,6 +111,9 @@ private:
static const int clipboard_timeout;
+ bool m_incr_active;
+ bool m_clipboard_closing;
+ xcb_timestamp_t m_incr_receive_time;
};
#endif // QT_NO_CLIPBOARD
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index ff5b36c448..d6f64d29fd 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -1164,6 +1164,12 @@ void QXcbConnection::processXcbEvents()
continue;
}
+ bool accepted = false;
+ if (clipboard()->processIncr())
+ clipboard()->incrTransactionPeeker(event, accepted);
+ if (accepted)
+ continue;
+
QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
while (it != m_peekFuncs.end()) {
// These callbacks return true if the event is what they were
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 46c3fdce5c..1f5169e8d9 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -648,7 +648,6 @@ void QXcbWindow::show()
if (!transientXcbParent)
transientXcbParent = static_cast<QXcbScreen *>(screen())->clientLeader();
if (transientXcbParent) { // ICCCM 4.1.2.6
- m_gravity = XCB_GRAVITY_CENTER;
Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
1, &transientXcbParent));
@@ -1304,9 +1303,6 @@ QRect QXcbWindow::windowToWmGeometry(QRect r) const
r.translate(m_frameMargins.left(), m_frameMargins.top());
} else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) {
r.translate(-m_frameMargins.left(), -m_frameMargins.top());
- } else if (!frameInclusive && m_gravity == XCB_GRAVITY_CENTER) {
- r.translate(-(m_frameMargins.left() - m_frameMargins.right())/2,
- -(m_frameMargins.top() - m_frameMargins.bottom())/2);
}
return r;
}
diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm
index 9839268af4..37333f2593 100644
--- a/src/printsupport/dialogs/qprintdialog_mac.mm
+++ b/src/printsupport/dialogs/qprintdialog_mac.mm
@@ -197,7 +197,7 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
// close down during the cleanup (QTBUG-17913):
qApp->processEvents(QEventLoop::ExcludeUserInputEvents, QEventLoop::ExcludeSocketNotifiers);
- QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] init];
+ QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] initWithNSPrintInfo:printInfo];
if (modality == Qt::ApplicationModal || !q->parentWidget()) {
if (modality == Qt::NonModal)
qWarning("QPrintDialog is required to be modal on OS X");
diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp
index 55b17c05eb..d0b825ac21 100644
--- a/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp
+++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp
@@ -52,12 +52,12 @@ if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0) {
//! [1]
-if (v.typeName() == "PGconn*") {
+if (qstrcmp(v.typeName(), "PGconn*")) {
PGconn *handle = *static_cast<PGconn **>(v.data());
if (handle != 0) ...
}
-if (v.typeName() == "MYSQL*") {
+if (qstrcmp(v.typeName(), "MYSQL*")) {
MYSQL *handle = *static_cast<MYSQL **>(v.data());
if (handle != 0) ...
}
diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
index 4105a43735..20ef7b5a76 100644
--- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
+++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
@@ -79,6 +79,8 @@ private slots:
void QTBUG2331();
void QTBUG2331_data() { basicTest_data(); }
+ void signalsEmittedAfterFileMoved();
+
private:
QString m_tempDirPattern;
};
@@ -596,5 +598,84 @@ void tst_QFileSystemWatcher::QTBUG2331()
QCOMPARE(watcher.directories(), QStringList());
}
+class SignalReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ SignalReceiver(const QDir &moveSrcDir,
+ const QString &moveDestination,
+ QFileSystemWatcher *watcher,
+ QObject *parent = 0)
+ : QObject(parent),
+ added(false),
+ moveSrcDir(moveSrcDir),
+ moveDestination(QDir(moveDestination)),
+ watcher(watcher)
+ {}
+
+public slots:
+ void fileChanged(const QString &path)
+ {
+ QFileInfo finfo(path);
+
+ QCOMPARE(finfo.absolutePath(), moveSrcDir.absolutePath());
+
+ if (!added) {
+ foreach (const QFileInfo &fi, moveDestination.entryInfoList(QDir::Files | QDir::NoSymLinks))
+ watcher->addPath(fi.absoluteFilePath());
+ added = true;
+ }
+ }
+
+private:
+ bool added;
+ QDir moveSrcDir;
+ QDir moveDestination;
+ QFileSystemWatcher *watcher;
+};
+
+// regression test for QTBUG-33211.
+// using inotify backend if a file is moved and then added to the watcher
+// before all the fileChanged signals are emitted the remaining signals are
+// emitted with the destination path instead of the starting path
+void tst_QFileSystemWatcher::signalsEmittedAfterFileMoved()
+{
+ QTemporaryDir temporaryDirectory(m_tempDirPattern);
+ QVERIFY(temporaryDirectory.isValid());
+ QDir testDir(temporaryDirectory.path());
+ QVERIFY(testDir.mkdir("movehere"));
+ QString movePath = testDir.filePath("movehere");
+
+ for (int i = 0; i < 10; i++) {
+ QFile f(testDir.filePath(QString("test%1.txt").arg(i)));
+ QVERIFY(f.open(QIODevice::WriteOnly));
+ f.write(QByteArray("i am " + i));
+ f.close();
+ }
+
+ QFileSystemWatcher watcher;
+ QVERIFY(watcher.addPath(testDir.path()));
+ QVERIFY(watcher.addPath(movePath));
+
+ // add files to watcher
+ QFileInfoList files = testDir.entryInfoList(QDir::Files | QDir::NoSymLinks);
+ foreach (const QFileInfo &finfo, files)
+ QVERIFY(watcher.addPath(finfo.absoluteFilePath()));
+
+ // create the signal receiver
+ SignalReceiver signalReceiver(testDir, movePath, &watcher);
+ connect(&watcher, SIGNAL(fileChanged(QString)), &signalReceiver, SLOT(fileChanged(QString)));
+
+ // watch signals
+ QSignalSpy changedSpy(&watcher, SIGNAL(fileChanged(QString)));
+ QVERIFY(changedSpy.isValid());
+
+ // move files to second directory
+ foreach (const QFileInfo &finfo, files)
+ QVERIFY(testDir.rename(finfo.fileName(), QString("movehere/%2").arg(finfo.fileName())));
+
+ QTRY_COMPARE(changedSpy.count(), 10);
+}
+
QTEST_MAIN(tst_QFileSystemWatcher)
#include "tst_qfilesystemwatcher.moc"
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index 6c56d3c2fa..90137079f3 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -1587,6 +1587,8 @@ void tst_QTextLayout::testTabDPIScale()
case QPaintDevice::PdmPhysicalDpiX:
case QPaintDevice::PdmPhysicalDpiY:
return 72;
+ case QPaintDevice::PdmDevicePixelRatio:
+ ; // fall through
}
return 0;
}
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index c3faa93309..0425db3098 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -114,6 +114,7 @@ private slots:
void about();
void detailsText();
void detailsButtonText();
+ void expandDetails_QTBUG_32473();
#ifndef Q_OS_MAC
void shortcut();
@@ -137,6 +138,19 @@ private:
QTimer keySendTimer;
};
+class tst_ResizingMessageBox : public QMessageBox
+{
+public:
+ tst_ResizingMessageBox() : QMessageBox(), resized(false) { }
+ bool resized;
+
+protected:
+ void resizeEvent ( QResizeEvent * event ) {
+ resized = true;
+ QMessageBox::resizeEvent(event);
+ }
+};
+
tst_QMessageBox::tst_QMessageBox() : keyToSend(-1)
{
}
@@ -603,6 +617,37 @@ void tst_QMessageBox::detailsButtonText()
}
}
+void tst_QMessageBox::expandDetails_QTBUG_32473()
+{
+ tst_ResizingMessageBox box;
+ box.setDetailedText("bla");
+ box.show();
+ QApplication::postEvent(&box, new QEvent(QEvent::LanguageChange));
+ QApplication::processEvents();
+ QDialogButtonBox* bb = box.findChild<QDialogButtonBox*>("qt_msgbox_buttonbox");
+ QVERIFY(bb);
+
+ QList<QAbstractButton *> list = bb->buttons();
+ QAbstractButton* moreButton = NULL;
+ foreach (QAbstractButton* btn, list)
+ if (btn && bb->buttonRole(btn) == QDialogButtonBox::ActionRole)
+ moreButton = btn;
+ QVERIFY(moreButton);
+ QVERIFY(QTest::qWaitForWindowExposed(&box));
+ QRect geom = box.geometry();
+ box.resized = false;
+ moreButton->click();
+ QTRY_VERIFY(box.resized);
+ // After we receive the expose event for a second widget, it's likely
+ // that the window manager is also done manipulating the first QMessageBox.
+ QWidget fleece;
+ fleece.show();
+ QTest::qWaitForWindowExposed(&fleece);
+ if (geom.topLeft() == box.geometry().topLeft())
+ QTest::qWait(500);
+ QCOMPARE(geom.topLeft(), box.geometry().topLeft());
+}
+
void tst_QMessageBox::incorrectDefaultButton()
{
keyToSend = Qt::Key_Escape;