Merge "Merge branch 'stable' into dev" into refs/staging/dev
This commit is contained in:
commit
4cebef621b
@ -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"
|
||||
|
@ -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 \
|
||||
|
@ -39,7 +39,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef GRAPHICSVIEW_H
|
||||
#define GRAPHICSVIEW
|
||||
#define GRAPHICSVIEW_H
|
||||
|
||||
#include <QtWidgets/QGraphicsView>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
@ -645,114 +644,11 @@
|
||||
a TCP server asynchronously.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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
|
||||
|
@ -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
|
||||
|
@ -78,11 +78,14 @@ public:
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -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, ¤tAction);
|
||||
if (currentAction.sa_handler == qt_sa_sigchld_handler) {
|
||||
if (currentAction.sa_sigaction == qt_sa_sigchld_sigaction) {
|
||||
::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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}
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -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)
|
||||
|
@ -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 &, 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();
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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) ...
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -1587,6 +1587,8 @@ void tst_QTextLayout::testTabDPIScale()
|
||||
case QPaintDevice::PdmPhysicalDpiX:
|
||||
case QPaintDevice::PdmPhysicalDpiY:
|
||||
return 72;
|
||||
case QPaintDevice::PdmDevicePixelRatio:
|
||||
; // fall through
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user