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.names = *
|
||||||
# manifestmeta.global.tags = qt5
|
# 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" \
|
manifestmeta.highlighted.names = "QtQuick/Qt Quick Demo - Same Game" \
|
||||||
"QtQuick/Qt Quick Demo - Photo Surface" \
|
"QtQuick/Qt Quick Demo - Photo Surface" \
|
||||||
@ -168,3 +168,28 @@ manifestmeta.android.names = "QtQuick/Qt Quick Demo - Maroon*" \
|
|||||||
"QtWidgets/Address Book Example"
|
"QtWidgets/Address Book Example"
|
||||||
|
|
||||||
manifestmeta.android.tags = android
|
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_CORE_EXPORT_INLINE \
|
||||||
Q_DBUS_EXPORT \
|
Q_DBUS_EXPORT \
|
||||||
Q_DECL_CONSTEXPR \
|
Q_DECL_CONSTEXPR \
|
||||||
|
Q_DECL_DEPRECATED \
|
||||||
Q_DECL_NOEXCEPT \
|
Q_DECL_NOEXCEPT \
|
||||||
Q_DECL_NOTHROW \
|
Q_DECL_NOTHROW \
|
||||||
Q_DECLARATIVE_EXPORT \
|
Q_DECLARATIVE_EXPORT \
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef GRAPHICSVIEW_H
|
#ifndef GRAPHICSVIEW_H
|
||||||
#define GRAPHICSVIEW
|
#define GRAPHICSVIEW_H
|
||||||
|
|
||||||
#include <QtWidgets/QGraphicsView>
|
#include <QtWidgets/QGraphicsView>
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@
|
|||||||
Random access iterators can be faster in cases where Qt Concurrent is iterating
|
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
|
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
|
in the container. In addition, using random access iterators allows Qt Concurrent
|
||||||
to provide progress information trough QFuture::progressValue() and QFutureWatcher::
|
to provide progress information trough QFuture::progressValue() and
|
||||||
progressValueChanged().
|
QFutureWatcher::progressValueChanged().
|
||||||
|
|
||||||
The non in-place modifying functions such as mapped() and filtered() makes a
|
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
|
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
|
\brief The <QtConcurrentFilter> header provides concurrent Filter and
|
||||||
Filter-Reduce.
|
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
|
The QtConcurrent::filter(), QtConcurrent::filtered() and
|
||||||
QtConcurrent::filteredReduced() functions filter items in a sequence such
|
QtConcurrent::filteredReduced() functions filter items in a sequence such
|
||||||
|
@ -47,8 +47,8 @@
|
|||||||
possible to write multi-threaded programs without using low-level
|
possible to write multi-threaded programs without using low-level
|
||||||
threading primitives.
|
threading primitives.
|
||||||
|
|
||||||
See the \l {Concurrent Programming}{Qt Concurrent} chapter in
|
See the \l {Qt Concurrent} module documentation for an overview of available
|
||||||
the \l{threads.html}{threading} documentation.
|
functions, or see below for detailed information on each function.
|
||||||
|
|
||||||
\inheaderfile QtConcurrent
|
\inheaderfile QtConcurrent
|
||||||
\ingroup thread
|
\ingroup thread
|
||||||
@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
\brief The <QtConcurrentMap> header provides concurrent Map and MapReduce.
|
\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
|
The QtConcurrent::map(), QtConcurrent::mapped() and
|
||||||
QtConcurrent::mappedReduced() functions run computations in parallel on
|
QtConcurrent::mappedReduced() functions run computations in parallel on
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
\ingroup thread
|
\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 QtConcurrent::run() function runs a function in a separate thread.
|
||||||
The return value of the function is made available through the QFuture API.
|
The return value of the function is made available through the QFuture API.
|
||||||
|
@ -63,7 +63,6 @@
|
|||||||
\li \l{Synchronizing Threads}
|
\li \l{Synchronizing Threads}
|
||||||
\li \l{Reentrancy and Thread-Safety}
|
\li \l{Reentrancy and Thread-Safety}
|
||||||
\li \l{Threads and QObjects}
|
\li \l{Threads and QObjects}
|
||||||
\li \l{Concurrent Programming}
|
|
||||||
\li \l{Thread-Support in Qt Modules}
|
\li \l{Thread-Support in Qt Modules}
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
@ -449,7 +448,7 @@
|
|||||||
|
|
||||||
\previouspage Reentrancy and Thread Safety
|
\previouspage Reentrancy and Thread Safety
|
||||||
\contentspage Thread Support in Qt
|
\contentspage Thread Support in Qt
|
||||||
\nextpage Concurrent Programming
|
\nextpage Thread-Support in Qt Modules
|
||||||
|
|
||||||
QThread inherits QObject. It emits signals to indicate that the
|
QThread inherits QObject. It emits signals to indicate that the
|
||||||
thread started or finished executing, and provides a few slots as
|
thread started or finished executing, and provides a few slots as
|
||||||
@ -645,114 +644,11 @@
|
|||||||
a TCP server asynchronously.
|
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
|
\page threads-modules.html
|
||||||
\title Thread-Support in Qt Modules
|
\title Thread-Support in Qt Modules
|
||||||
|
|
||||||
\previouspage Concurrent Programming
|
\previouspage Threads and QObjects
|
||||||
\contentspage Thread Support in Qt
|
\contentspage Thread Support in Qt
|
||||||
|
|
||||||
\section1 Threads and the SQL Module
|
\section1 Threads and the SQL Module
|
||||||
|
@ -365,11 +365,11 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
|
|||||||
// qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask;
|
// qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask;
|
||||||
|
|
||||||
int id = event.wd;
|
int id = event.wd;
|
||||||
QString path = idToPath.value(id);
|
QString path = getPathFromID(id);
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
// perhaps a directory?
|
// perhaps a directory?
|
||||||
id = -id;
|
id = -id;
|
||||||
path = idToPath.value(id);
|
path = getPathFromID(id);
|
||||||
if (path.isEmpty())
|
if (path.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -378,8 +378,9 @@ void QInotifyFileSystemWatcherEngine::readFromInotify()
|
|||||||
|
|
||||||
if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) {
|
if ((event.mask & (IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT)) != 0) {
|
||||||
pathToID.remove(path);
|
pathToID.remove(path);
|
||||||
idToPath.remove(id);
|
idToPath.remove(id, getPathFromID(id));
|
||||||
inotify_rm_watch(inotifyFd, event.wd);
|
if (!idToPath.contains(id))
|
||||||
|
inotify_rm_watch(inotifyFd, event.wd);
|
||||||
|
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
emit directoryChanged(path, true);
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QT_NO_FILESYSTEMWATCHER
|
#endif // QT_NO_FILESYSTEMWATCHER
|
||||||
|
@ -78,11 +78,14 @@ public:
|
|||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void readFromInotify();
|
void readFromInotify();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString getPathFromID(int id) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QInotifyFileSystemWatcherEngine(int fd, QObject *parent);
|
QInotifyFileSystemWatcherEngine(int fd, QObject *parent);
|
||||||
int inotifyFd;
|
int inotifyFd;
|
||||||
QHash<QString, int> pathToID;
|
QHash<QString, int> pathToID;
|
||||||
QHash<int, QString> idToPath;
|
QMultiHash<int, QString> idToPath;
|
||||||
QSocketNotifier notifier;
|
QSocketNotifier notifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,17 +121,33 @@ static const int errorBufferMax = 512;
|
|||||||
|
|
||||||
static int qt_qprocess_deadChild_pipe[2];
|
static int qt_qprocess_deadChild_pipe[2];
|
||||||
static struct sigaction qt_sa_old_sigchld_handler;
|
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);
|
qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1);
|
||||||
#if defined (QPROCESS_DEBUG)
|
#if defined (QPROCESS_DEBUG)
|
||||||
fprintf(stderr, "*** SIGCHLD\n");
|
fprintf(stderr, "*** SIGCHLD\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// load it as volatile
|
// load as volatile
|
||||||
void (*oldAction)(int) = ((volatile struct sigaction *)&qt_sa_old_sigchld_handler)->sa_handler;
|
volatile struct sigaction *vsa = &qt_sa_old_sigchld_handler;
|
||||||
if (oldAction && oldAction != SIG_IGN)
|
|
||||||
oldAction(signum);
|
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)
|
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
|
// set up the SIGCHLD handler, which writes a single byte to the dead
|
||||||
// child pipe every time a child dies.
|
// child pipe every time a child dies.
|
||||||
|
|
||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
memset(&action, 0, sizeof(action));
|
// use the old handler as template, i.e., preserve the signal mask
|
||||||
action.sa_handler = qt_sa_sigchld_handler;
|
// otherwise the original signal handler might be interrupted although it
|
||||||
action.sa_flags = SA_NOCLDSTOP;
|
// 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);
|
::sigaction(SIGCHLD, &action, &qt_sa_old_sigchld_handler);
|
||||||
|
|
||||||
processManagerInstance = this;
|
processManagerInstance = this;
|
||||||
@ -225,7 +247,7 @@ QProcessManager::~QProcessManager()
|
|||||||
|
|
||||||
struct sigaction currentAction;
|
struct sigaction currentAction;
|
||||||
::sigaction(SIGCHLD, 0, ¤tAction);
|
::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);
|
::sigaction(SIGCHLD, &qt_sa_old_sigchld_handler, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +47,7 @@
|
|||||||
|
|
||||||
\ingroup thread
|
\ingroup thread
|
||||||
|
|
||||||
To start a computation, use one of the APIs in the
|
To start a computation, use one of the APIs in the \l {Qt Concurrent} framework.
|
||||||
\l {Concurrent Programming}{Qt Concurrent} framework.
|
|
||||||
|
|
||||||
QFuture allows threads to be synchronized against one or more results
|
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
|
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.
|
To interact with running tasks using signals and slots, use QFutureWatcher.
|
||||||
|
|
||||||
\sa QFutureWatcher, {Concurrent Programming}{Qt Concurrent}
|
\sa QFutureWatcher, {Qt Concurrent}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \fn QFuture::QFuture()
|
/*! \fn QFuture::QFuture()
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
You can query the status of the cancel-on-wait feature using the
|
You can query the status of the cancel-on-wait feature using the
|
||||||
cancelOnWait() function.
|
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
|
QFutureWatcher<void> as well. This is useful if only status or progress
|
||||||
information is needed; not the actual result data.
|
information is needed; not the actual result data.
|
||||||
|
|
||||||
\sa QFuture, {Concurrent Programming}{Qt Concurrent}
|
\sa QFuture, {Qt Concurrent}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \fn QFutureWatcher::QFutureWatcher(QObject *parent)
|
/*! \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).
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
** Contact: http://www.qt-project.org/legal
|
** 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.setColorCount(2);
|
||||||
image.setColor(1, qRgb(0,0,0));
|
image.setColor(1, qRgb(0,0,0));
|
||||||
image.setColor(0, qRgb(255,255,255));
|
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)) {
|
} else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||||
png_set_expand(png_ptr);
|
png_set_expand(png_ptr);
|
||||||
png_set_strip_16(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)
|
QPngHandlerPrivate::AllocatedMemoryPointers &, QSize scaledSize)
|
||||||
{
|
{
|
||||||
|
|
||||||
png_uint_32 width;
|
png_uint_32 width = 0;
|
||||||
png_uint_32 height;
|
png_uint_32 height = 0;
|
||||||
png_int_32 offset_x;
|
png_int_32 offset_x = 0;
|
||||||
png_int_32 offset_y;
|
png_int_32 offset_y = 0;
|
||||||
|
|
||||||
int bit_depth;
|
int bit_depth = 0;
|
||||||
int color_type;
|
int color_type = 0;
|
||||||
int unit_type;
|
int unit_type = PNG_OFFSET_PIXEL;
|
||||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
|
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);
|
png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);
|
||||||
uchar *data = outImage->bits();
|
uchar *data = outImage->bits();
|
||||||
|
@ -2293,13 +2293,30 @@ bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
|
|||||||
return qFuzzyCompare(xScale, yScale);
|
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();
|
+ transform.m21() * transform.m21();
|
||||||
const qreal yScale = transform.m12() * transform.m12()
|
const qreal yScale1 = transform.m12() * transform.m12()
|
||||||
+ transform.m22() * transform.m22();
|
+ transform.m22() * transform.m22();
|
||||||
if (scale)
|
|
||||||
*scale = qSqrt(qMax(xScale, yScale));
|
// scale then rotate: compare rows
|
||||||
return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale);
|
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
|
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.
|
// 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::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);
|
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[i].authenticator);
|
||||||
if (priv && priv->method != QAuthenticatorPrivate::None) {
|
if (priv && priv->method != QAuthenticatorPrivate::None) {
|
||||||
QByteArray response = priv->calculateResponse(request.d->methodName(), request.d->uri(false));
|
QByteArray response = priv->calculateResponse(request.d->methodName(), request.d->uri(false));
|
||||||
|
@ -236,8 +236,8 @@ bool QHttpNetworkConnectionChannel::sendRequest()
|
|||||||
QAuthenticator &auth = authenticator;
|
QAuthenticator &auth = authenticator;
|
||||||
if (url.userName() != auth.user()
|
if (url.userName() != auth.user()
|
||||||
|| (!url.password().isEmpty() && url.password() != auth.password())) {
|
|| (!url.password().isEmpty() && url.password() != auth.password())) {
|
||||||
auth.setUser(url.userName());
|
auth.setUser(url.userName(QUrl::FullyDecoded));
|
||||||
auth.setPassword(url.password());
|
auth.setPassword(url.password(QUrl::FullyDecoded));
|
||||||
connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false);
|
connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false);
|
||||||
}
|
}
|
||||||
// clear the userinfo, since we use the same request for resending
|
// 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 credentials are included in the url, then use them
|
||||||
if (!url.userName().isEmpty()
|
if (!url.userName().isEmpty()
|
||||||
&& !url.password().isEmpty()) {
|
&& !url.password().isEmpty()) {
|
||||||
authenticator->setUser(url.userName());
|
authenticator->setUser(url.userName(QUrl::FullyDecoded));
|
||||||
authenticator->setPassword(url.password());
|
authenticator->setPassword(url.password(QUrl::FullyDecoded));
|
||||||
*urlForLastAuthentication = url;
|
*urlForLastAuthentication = url;
|
||||||
authenticationManager->cacheCredentials(url, authenticator);
|
authenticationManager->cacheCredentials(url, authenticator);
|
||||||
return;
|
return;
|
||||||
|
@ -115,7 +115,7 @@ QAccessibleInterface *AccessibleFactory::create(const QString &classname, QObjec
|
|||||||
QToolButton *tb = qobject_cast<QToolButton*>(widget);
|
QToolButton *tb = qobject_cast<QToolButton*>(widget);
|
||||||
if (!tb->menu())
|
if (!tb->menu())
|
||||||
role = tb->isCheckable() ? QAccessible::CheckBox : QAccessible::PushButton;
|
role = tb->isCheckable() ? QAccessible::CheckBox : QAccessible::PushButton;
|
||||||
else if (!tb->popupMode() != QToolButton::DelayedPopup)
|
else if (tb->popupMode() == QToolButton::DelayedPopup)
|
||||||
role = QAccessible::ButtonDropDown;
|
role = QAccessible::ButtonDropDown;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,7 +125,7 @@ public:
|
|||||||
QList<int> possibleKeys(const QKeyEvent *event) const;
|
QList<int> possibleKeys(const QKeyEvent *event) const;
|
||||||
|
|
||||||
void updateScreens();
|
void updateScreens();
|
||||||
QCocoaScreen *screenAtIndex(int index) const { return mScreens.at(index); }
|
QCocoaScreen *screenAtIndex(int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -343,6 +343,14 @@ void QCocoaIntegration::updateScreens()
|
|||||||
screen->setVirtualSiblings(siblings);
|
screen->setVirtualSiblings(siblings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCocoaScreen *QCocoaIntegration::screenAtIndex(int index)
|
||||||
|
{
|
||||||
|
if (index >= mScreens.count())
|
||||||
|
updateScreens();
|
||||||
|
|
||||||
|
return mScreens.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
|
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
|
||||||
{
|
{
|
||||||
switch (cap) {
|
switch (cap) {
|
||||||
|
@ -157,12 +157,122 @@ private:
|
|||||||
QByteArray format_atoms;
|
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;
|
const int QXcbClipboard::clipboard_timeout = 5000;
|
||||||
|
|
||||||
QXcbClipboard::QXcbClipboard(QXcbConnection *c)
|
QXcbClipboard::QXcbClipboard(QXcbConnection *c)
|
||||||
: QXcbObject(c), QPlatformClipboard()
|
: QXcbObject(c), QPlatformClipboard()
|
||||||
, m_requestor(XCB_NONE)
|
, m_requestor(XCB_NONE)
|
||||||
, m_owner(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::Clipboard == 0);
|
||||||
Q_ASSERT(QClipboard::Selection == 1);
|
Q_ASSERT(QClipboard::Selection == 1);
|
||||||
@ -200,6 +310,7 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
|
|||||||
|
|
||||||
QXcbClipboard::~QXcbClipboard()
|
QXcbClipboard::~QXcbClipboard()
|
||||||
{
|
{
|
||||||
|
m_clipboard_closing = true;
|
||||||
// Transfer the clipboard content to the clipboard manager if we own a selection
|
// Transfer the clipboard content to the clipboard manager if we own a selection
|
||||||
if (m_timestamp[QClipboard::Clipboard] != XCB_CURRENT_TIME ||
|
if (m_timestamp[QClipboard::Clipboard] != XCB_CURRENT_TIME ||
|
||||||
m_timestamp[QClipboard::Selection] != 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
|
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)
|
// Motif clients (since Motif doesn't support INCR)
|
||||||
static xcb_atom_t motif_clip_temporary = atom(QXcbAtom::CLIP_TEMPORARY);
|
static xcb_atom_t motif_clip_temporary = atom(QXcbAtom::CLIP_TEMPORARY);
|
||||||
bool allow_incr = property != motif_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
|
// X_ChangeProperty protocol request is 24 bytes
|
||||||
const int increment = (xcb_get_maximum_request_length(xcb_connection()) * 4) - 24;
|
const int increment = (xcb_get_maximum_request_length(xcb_connection()) * 4) - 24;
|
||||||
if (data.size() > increment && allow_incr) {
|
if (data.size() > increment && allow_incr) {
|
||||||
long bytes = data.size();
|
long bytes = data.size();
|
||||||
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, property,
|
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, window, property,
|
||||||
atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
|
atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
|
||||||
|
new INCRTransaction(connection(), window, property, data, increment,
|
||||||
// (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment);
|
atomFormat, dataFormat, clipboard_timeout);
|
||||||
qWarning("QXcbClipboard: INCR is unimplemented");
|
|
||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,7 +734,7 @@ static inline int maxSelectionIncr(xcb_connection_t *c)
|
|||||||
return (l > 65536 ? 65536*4 : l*4) - 100;
|
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());
|
int maxsize = maxSelectionIncr(xcb_connection());
|
||||||
ulong bytes_left; // bytes_after
|
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.
|
// correct size, not 0-term.
|
||||||
if (size)
|
if (size)
|
||||||
*size = buffer_offset;
|
*size = buffer_offset;
|
||||||
|
if (*type == atom(QXcbAtom::INCR))
|
||||||
|
m_incr_receive_time = connection()->getTimestamp();
|
||||||
if (deleteProperty)
|
if (deleteProperty)
|
||||||
xcb_delete_property(xcb_connection(), win, property);
|
xcb_delete_property(xcb_connection(), win, property);
|
||||||
|
|
||||||
@ -791,6 +915,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
|
|||||||
bool alloc_error = false;
|
bool alloc_error = false;
|
||||||
int length;
|
int length;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
xcb_timestamp_t prev_time = m_incr_receive_time;
|
||||||
|
|
||||||
if (nbytes > 0) {
|
if (nbytes > 0) {
|
||||||
// Reserve buffer + zero-terminator (for text data)
|
// 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);
|
xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY, clipboard_timeout);
|
||||||
if (!ge)
|
if (!ge)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge;
|
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;
|
continue;
|
||||||
|
prev_time = event->time;
|
||||||
|
|
||||||
if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) {
|
if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) {
|
||||||
if (length == 0) { // no more data, we're done
|
if (length == 0) { // no more data, we're done
|
||||||
if (nullterm) {
|
if (nullterm) {
|
||||||
|
@ -78,11 +78,15 @@ public:
|
|||||||
void handleSelectionClearRequest(xcb_selection_clear_event_t *event);
|
void handleSelectionClearRequest(xcb_selection_clear_event_t *event);
|
||||||
void handleXFixesSelectionRequest(xcb_xfixes_selection_notify_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 clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm);
|
||||||
|
|
||||||
QByteArray getDataInFormat(xcb_atom_t modeAtom, xcb_atom_t fmtatom);
|
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;
|
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);
|
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;
|
static const int clipboard_timeout;
|
||||||
|
|
||||||
|
bool m_incr_active;
|
||||||
|
bool m_clipboard_closing;
|
||||||
|
xcb_timestamp_t m_incr_receive_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_NO_CLIPBOARD
|
#endif // QT_NO_CLIPBOARD
|
||||||
|
@ -1164,6 +1164,12 @@ void QXcbConnection::processXcbEvents()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool accepted = false;
|
||||||
|
if (clipboard()->processIncr())
|
||||||
|
clipboard()->incrTransactionPeeker(event, accepted);
|
||||||
|
if (accepted)
|
||||||
|
continue;
|
||||||
|
|
||||||
QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
|
QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
|
||||||
while (it != m_peekFuncs.end()) {
|
while (it != m_peekFuncs.end()) {
|
||||||
// These callbacks return true if the event is what they were
|
// These callbacks return true if the event is what they were
|
||||||
|
@ -648,7 +648,6 @@ void QXcbWindow::show()
|
|||||||
if (!transientXcbParent)
|
if (!transientXcbParent)
|
||||||
transientXcbParent = static_cast<QXcbScreen *>(screen())->clientLeader();
|
transientXcbParent = static_cast<QXcbScreen *>(screen())->clientLeader();
|
||||||
if (transientXcbParent) { // ICCCM 4.1.2.6
|
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,
|
Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
|
||||||
XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
|
XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
|
||||||
1, &transientXcbParent));
|
1, &transientXcbParent));
|
||||||
@ -1304,9 +1303,6 @@ QRect QXcbWindow::windowToWmGeometry(QRect r) const
|
|||||||
r.translate(m_frameMargins.left(), m_frameMargins.top());
|
r.translate(m_frameMargins.left(), m_frameMargins.top());
|
||||||
} else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) {
|
} else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) {
|
||||||
r.translate(-m_frameMargins.left(), -m_frameMargins.top());
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
|
|||||||
// close down during the cleanup (QTBUG-17913):
|
// close down during the cleanup (QTBUG-17913):
|
||||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents, QEventLoop::ExcludeSocketNotifiers);
|
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::ApplicationModal || !q->parentWidget()) {
|
||||||
if (modality == Qt::NonModal)
|
if (modality == Qt::NonModal)
|
||||||
qWarning("QPrintDialog is required to be modal on OS X");
|
qWarning("QPrintDialog is required to be modal on OS X");
|
||||||
|
@ -52,12 +52,12 @@ if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0) {
|
|||||||
|
|
||||||
|
|
||||||
//! [1]
|
//! [1]
|
||||||
if (v.typeName() == "PGconn*") {
|
if (qstrcmp(v.typeName(), "PGconn*")) {
|
||||||
PGconn *handle = *static_cast<PGconn **>(v.data());
|
PGconn *handle = *static_cast<PGconn **>(v.data());
|
||||||
if (handle != 0) ...
|
if (handle != 0) ...
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v.typeName() == "MYSQL*") {
|
if (qstrcmp(v.typeName(), "MYSQL*")) {
|
||||||
MYSQL *handle = *static_cast<MYSQL **>(v.data());
|
MYSQL *handle = *static_cast<MYSQL **>(v.data());
|
||||||
if (handle != 0) ...
|
if (handle != 0) ...
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,8 @@ private slots:
|
|||||||
void QTBUG2331();
|
void QTBUG2331();
|
||||||
void QTBUG2331_data() { basicTest_data(); }
|
void QTBUG2331_data() { basicTest_data(); }
|
||||||
|
|
||||||
|
void signalsEmittedAfterFileMoved();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_tempDirPattern;
|
QString m_tempDirPattern;
|
||||||
};
|
};
|
||||||
@ -596,5 +598,84 @@ void tst_QFileSystemWatcher::QTBUG2331()
|
|||||||
QCOMPARE(watcher.directories(), QStringList());
|
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)
|
QTEST_MAIN(tst_QFileSystemWatcher)
|
||||||
#include "tst_qfilesystemwatcher.moc"
|
#include "tst_qfilesystemwatcher.moc"
|
||||||
|
@ -1587,6 +1587,8 @@ void tst_QTextLayout::testTabDPIScale()
|
|||||||
case QPaintDevice::PdmPhysicalDpiX:
|
case QPaintDevice::PdmPhysicalDpiX:
|
||||||
case QPaintDevice::PdmPhysicalDpiY:
|
case QPaintDevice::PdmPhysicalDpiY:
|
||||||
return 72;
|
return 72;
|
||||||
|
case QPaintDevice::PdmDevicePixelRatio:
|
||||||
|
; // fall through
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ private slots:
|
|||||||
void about();
|
void about();
|
||||||
void detailsText();
|
void detailsText();
|
||||||
void detailsButtonText();
|
void detailsButtonText();
|
||||||
|
void expandDetails_QTBUG_32473();
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
void shortcut();
|
void shortcut();
|
||||||
@ -137,6 +138,19 @@ private:
|
|||||||
QTimer keySendTimer;
|
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)
|
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()
|
void tst_QMessageBox::incorrectDefaultButton()
|
||||||
{
|
{
|
||||||
keyToSend = Qt::Key_Escape;
|
keyToSend = Qt::Key_Escape;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user