From 112e53fdc4e46a5e94cb2d575d132e2015694407 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 28 Apr 2016 17:47:57 -0700 Subject: Don't store the pthread_t thread ID twice in QThread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was being stored once in QThreadPrivate and once in QThreadData, with the latter being hidden as a Qt::HANDLE. Besides saving a little bit of memory, this also solves a small data race condition that arises from trying to connect a signal to an object moved to that thread and then emit that signal shortly after the thread starts. Before this patch, QThreadData::threadId was initialized only by QThreadPrivate::start(), which meant that we were racing that initialization with this check in QMetaObject::activate: const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId; Task-number: QTBUG-52337 Change-Id: Ifea6e497f11a461db432ffff1449ae01f1099aae Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- src/corelib/thread/qthread.cpp | 6 +----- src/corelib/thread/qthread_p.h | 1 - src/corelib/thread/qthread_unix.cpp | 33 +++++++++++++++++---------------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index a0a2e76bda..8ea487e330 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -142,16 +142,12 @@ QThreadPrivate::QThreadPrivate(QThreadData *d) exited(false), returnCode(-1), stackSize(0), priority(QThread::InheritPriority), data(d) { -#if defined (Q_OS_UNIX) - thread_id = 0; -#elif defined (Q_OS_WIN) +#if defined (Q_OS_WIN) handle = 0; # ifndef Q_OS_WINRT id = 0; # endif waiters = 0; -#endif -#if defined (Q_OS_WIN) terminationEnabled = true; terminatePending = false; #endif diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index a0d354acdc..a56b879462 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -169,7 +169,6 @@ public: static QThread *threadForId(int id); #ifdef Q_OS_UNIX - pthread_t thread_id; QWaitCondition thread_done; static void *start(void *arg); diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index af4ce7c59e..3fc0ebfbb6 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -105,6 +105,8 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_THREAD +Q_STATIC_ASSERT(sizeof(pthread_t) == sizeof(Qt::HANDLE)); + enum { ThreadPriorityResetFlag = 0x80000000 }; #if defined(Q_OS_LINUX) && defined(__GLIBC__) && (defined(Q_CC_GNU) || defined(Q_CC_INTEL)) && !defined(QT_LINUXBASE) @@ -234,8 +236,6 @@ QThreadData *QThreadData::current(bool createIfNecessary) void QAdoptedThread::init() { - Q_D(QThread); - d->thread_id = pthread_self(); } /* @@ -325,10 +325,11 @@ void *QThreadPrivate::start(void *arg) // sets the name of the current thread. QString objectName = thr->objectName(); + pthread_t thread_id = reinterpret_cast(data->threadId); if (Q_LIKELY(objectName.isEmpty())) - setCurrentThreadName(thr->d_func()->thread_id, thr->metaObject()->className()); + setCurrentThreadName(thread_id, thr->metaObject()->className()); else - setCurrentThreadName(thr->d_func()->thread_id, objectName.toLocal8Bit()); + setCurrentThreadName(thread_id, objectName.toLocal8Bit()); } #endif @@ -369,7 +370,6 @@ void QThreadPrivate::finish(void *arg) locker.relock(); } - d->thread_id = 0; d->running = false; d->finished = true; d->interruptionRequested = false; @@ -615,15 +615,16 @@ void QThread::start(Priority priority) } int code = - pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this); + pthread_create(reinterpret_cast(&d->data->threadId), &attr, + QThreadPrivate::start, this); if (code == EPERM) { // caller does not have permission to set the scheduling // parameters/policy #if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING) pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED); #endif - code = - pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this); + code = pthread_create(reinterpret_cast(&d->data->threadId), &attr, + QThreadPrivate::start, this); } pthread_attr_destroy(&attr); @@ -633,7 +634,7 @@ void QThread::start(Priority priority) d->running = false; d->finished = false; - d->thread_id = 0; + d->data->threadId = 0; } } @@ -643,10 +644,10 @@ void QThread::terminate() Q_D(QThread); QMutexLocker locker(&d->mutex); - if (!d->thread_id) + if (!d->data->threadId) return; - int code = pthread_cancel(d->thread_id); + int code = pthread_cancel(reinterpret_cast(d->data->threadId)); if (code) { qWarning("QThread::start: Thread termination error: %s", qPrintable(qt_error_string((code)))); @@ -659,7 +660,7 @@ bool QThread::wait(unsigned long time) Q_D(QThread); QMutexLocker locker(&d->mutex); - if (d->thread_id == pthread_self()) { + if (reinterpret_cast(d->data->threadId) == pthread_self()) { qWarning("QThread::wait: Thread tried to wait on itself"); return false; } @@ -701,7 +702,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) int sched_policy; sched_param param; - if (pthread_getschedparam(thread_id, &sched_policy, ¶m) != 0) { + if (pthread_getschedparam(reinterpret_cast(data->threadId), &sched_policy, ¶m) != 0) { // failed to get the scheduling policy, don't bother setting // the priority qWarning("QThread::setPriority: Cannot get scheduler parameters"); @@ -717,15 +718,15 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) } param.sched_priority = prio; - int status = pthread_setschedparam(thread_id, sched_policy, ¶m); + int status = pthread_setschedparam(reinterpret_cast(data->threadId), sched_policy, ¶m); # ifdef SCHED_IDLE // were we trying to set to idle priority and failed? if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) { // reset to lowest priority possible - pthread_getschedparam(thread_id, &sched_policy, ¶m); + pthread_getschedparam(reinterpret_cast(data->threadId), &sched_policy, ¶m); param.sched_priority = sched_get_priority_min(sched_policy); - pthread_setschedparam(thread_id, sched_policy, ¶m); + pthread_setschedparam(reinterpret_cast(data->threadId), sched_policy, ¶m); } # else Q_UNUSED(status); -- cgit v1.2.3 From fda6324b4d471c2163c94d0c451a4bb4671b7b18 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 28 Apr 2016 18:25:52 -0700 Subject: Remove the use of QMutexPool from QtDBus loading of libdbus-1 Change-Id: Ifea6e497f11a461db432ffff1449b013c2302d38 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Marc Mutz --- src/dbus/qdbus_symbols.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp index 395a436869..1b8bcbcd05 100644 --- a/src/dbus/qdbus_symbols.cpp +++ b/src/dbus/qdbus_symbols.cpp @@ -36,7 +36,6 @@ #include #endif #include -#include #ifndef QT_NO_DBUS @@ -74,8 +73,10 @@ bool qdbus_loadLibDBus() static bool triedToLoadLibrary = false; #ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&qdbus_resolve_me)); + static QBasicMutex mutex; + QMutexLocker locker(&mutex); #endif + QLibrary *&lib = qdbus_libdbus; if (triedToLoadLibrary) return lib && lib->isLoaded(); -- cgit v1.2.3 From c9f9f54d3f79915723270b2a6d06216a54c87433 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 28 Apr 2016 18:36:31 -0700 Subject: Remove the use of QMutexPool in QHostInfo and QDnsLookup Q_GLOBAL_STATIC does the thread-safe protection for us. And who said we could only use non-POD types? We can just use a boolean! Change-Id: Ifea6e497f11a461db432ffff1449b0a88d75d194 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/network/kernel/qdnslookup_unix.cpp | 17 ++++++----------- src/network/kernel/qhostinfo_unix.cpp | 17 ++++++----------- src/network/kernel/qhostinfo_win.cpp | 14 ++++---------- 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp index dc8ec5a300..cb3bdfe8ff 100644 --- a/src/network/kernel/qdnslookup_unix.cpp +++ b/src/network/kernel/qdnslookup_unix.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -71,7 +70,7 @@ struct QDnsLookupStateDeleter } }; -static void resolveLibrary() +static bool resolveLibraryInternal() { QLibrary lib; #ifdef LIBRESOLV_SO @@ -81,7 +80,7 @@ static void resolveLibrary() { lib.setFileName(QLatin1String("resolv")); if (!lib.load()) - return; + return false; } local_dn_expand = dn_expand_proto(lib.resolve("__dn_expand")); @@ -105,19 +104,15 @@ static void resolveLibrary() local_res_nquery = res_nquery_proto(lib.resolve("res_9_nquery")); if (!local_res_nquery) local_res_nquery = res_nquery_proto(lib.resolve("res_nquery")); + + return true; } +Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal())) void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply) { // Load dn_expand, res_ninit and res_nquery on demand. - static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); - if (!triedResolve.loadAcquire()) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_ninit)); - if (!triedResolve.load()) { - resolveLibrary(); - triedResolve.storeRelease(true); - } - } + resolveLibrary(); // If dn_expand, res_ninit or res_nquery is missing, fail. if (!local_dn_expand || !local_res_nclose || !local_res_ninit || !local_res_nquery) { diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index 266a67771c..dabf1913cc 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -86,7 +85,7 @@ typedef void (*res_nclose_proto)(res_state_ptr); static res_nclose_proto local_res_nclose = 0; static res_state_ptr local_res = 0; -static void resolveLibrary() +static bool resolveLibraryInternal() { #if !defined(QT_NO_LIBRARY) && !defined(Q_OS_QNX) QLibrary lib; @@ -97,7 +96,7 @@ static void resolveLibrary() { lib.setFileName(QLatin1String("resolv")); if (!lib.load()) - return; + return false; } local_res_init = res_init_proto(lib.resolve("__res_init")); @@ -119,7 +118,10 @@ static void resolveLibrary() local_res_ninit = 0; } #endif + + return true; } +Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal())) QHostInfo QHostInfoAgent::fromName(const QString &hostName) { @@ -131,14 +133,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) #endif // Load res_init on demand. - static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); - if (!triedResolve.loadAcquire()) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_res_init)); - if (!triedResolve.load()) { - resolveLibrary(); - triedResolve.storeRelease(true); - } - } + resolveLibrary(); // If res_init is available, poll it. if (local_res_init) diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index 7e45e9f949..58816b355d 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -39,7 +39,6 @@ #include #include #include -#include QT_BEGIN_NAMESPACE @@ -72,7 +71,7 @@ static getnameinfoProto local_getnameinfo = 0; static getaddrinfoProto local_getaddrinfo = 0; static freeaddrinfoProto local_freeaddrinfo = 0; -static void resolveLibrary() +static bool resolveLibraryInternal() { // Attempt to resolve getaddrinfo(); without it we'll have to fall // back to gethostbyname(), which has no IPv6 support. @@ -89,7 +88,9 @@ static void resolveLibrary() local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo"); local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo"); #endif + return true; } +Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal())) static void translateWSAError(int error, QHostInfo *results) { @@ -117,14 +118,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QSysInfo::machineHostName(); // this initializes ws2_32.dll // Load res_init on demand. - static QBasicAtomicInt triedResolve = Q_BASIC_ATOMIC_INITIALIZER(false); - if (!triedResolve.loadAcquire()) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_getaddrinfo)); - if (!triedResolve.load()) { - resolveLibrary(); - triedResolve.storeRelease(true); - } - } + resolveLibrary(); QHostInfo results; -- cgit v1.2.3 From a4d26cf522b966056e47e47a004b7e4d668e3a2d Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Fri, 8 Apr 2016 16:55:39 +0300 Subject: QWindowsPipeWriter: ensure validity of the write buffer QWindowsPipeWriter uses asynchronous API to perform writing. Once a cycle has been started, the write buffer must remain valid until the write operation is completed. To avoid data corruption and possibly undefined behavior, this patch makes QWindowsPipeWriter::write() take a QByteArray, which it keeps alive for the duration of the write cycle. Autotest-by: Thomas Hartmann Task-number: QTBUG-52401 Change-Id: Ia35faee735c4e684267daa1f6bd689512b670cd2 Reviewed-by: Joerg Bornemann --- src/corelib/io/qprocess.cpp | 23 +---- src/corelib/io/qprocess_p.h | 2 +- src/corelib/io/qprocess_unix.cpp | 35 +++++-- src/corelib/io/qprocess_win.cpp | 10 +- src/corelib/io/qprocess_wince.cpp | 6 +- src/corelib/io/qwindowspipewriter.cpp | 41 +++++--- src/corelib/io/qwindowspipewriter_p.h | 4 +- src/network/socket/qlocalsocket.h | 2 +- src/network/socket/qlocalsocket_p.h | 3 +- src/network/socket/qlocalsocket_win.cpp | 24 ++--- .../socket/qlocalsocket/tst_qlocalsocket.cpp | 108 +++++++++++++++++++++ 11 files changed, 185 insertions(+), 73 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 68f7157ad2..502628489d 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1051,7 +1051,6 @@ bool QProcessPrivate::_q_canReadStandardError() */ bool QProcessPrivate::_q_canWrite() { - Q_Q(QProcess); if (stdinChannel.notifier) stdinChannel.notifier->setEnabled(false); @@ -1062,31 +1061,13 @@ bool QProcessPrivate::_q_canWrite() return false; } - qint64 written = writeToStdin(stdinChannel.buffer.readPointer(), - stdinChannel.buffer.nextDataBlockSize()); - if (written < 0) { - closeChannel(&stdinChannel); - setErrorAndEmit(QProcess::WriteError); - return false; - } + const bool writeSucceeded = writeToStdin(); -#if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::canWrite(), wrote %d bytes to the process input", int(written)); -#endif - - if (written != 0) { - stdinChannel.buffer.free(written); - if (!emittedBytesWritten) { - emittedBytesWritten = true; - emit q->bytesWritten(written); - emittedBytesWritten = false; - } - } if (stdinChannel.notifier && !stdinChannel.buffer.isEmpty()) stdinChannel.notifier->setEnabled(true); if (stdinChannel.buffer.isEmpty() && stdinChannel.closed) closeWriteChannel(); - return true; + return writeSucceeded; } /*! diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 436869462c..0af1903063 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -375,7 +375,7 @@ public: qint64 bytesAvailableInChannel(const Channel *channel) const; qint64 readFromChannel(const Channel *channel, char *data, qint64 maxlen); - qint64 writeToStdin(const char *data, qint64 maxlen); + bool writeToStdin(); void cleanup(); void setError(QProcess::ProcessError error, const QString &description = QString()); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index df13a2533e..fda91780d0 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -620,21 +620,36 @@ qint64 QProcessPrivate::readFromChannel(const Channel *channel, char *data, qint return bytesRead; } -qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) +bool QProcessPrivate::writeToStdin() { - qint64 written = qt_safe_write_nosignal(stdinChannel.pipe[1], data, maxlen); + const char *data = stdinChannel.buffer.readPointer(); + const qint64 bytesToWrite = stdinChannel.buffer.nextDataBlockSize(); + + qint64 written = qt_safe_write_nosignal(stdinChannel.pipe[1], data, bytesToWrite); #if defined QPROCESS_DEBUG - qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld", - data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written); + qDebug("QProcessPrivate::writeToStdin(), write(%p \"%s\", %lld) == %lld", + data, qt_prettyDebug(data, bytesToWrite, 16).constData(), bytesToWrite, written); if (written == -1) qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qPrintable(qt_error_string(errno))); #endif - // If the O_NONBLOCK flag is set and If some data can be written without blocking - // the process, write() will transfer what it can and return the number of bytes written. - // Otherwise, it will return -1 and set errno to EAGAIN - if (written == -1 && errno == EAGAIN) - written = 0; - return written; + if (written == -1) { + // If the O_NONBLOCK flag is set and If some data can be written without blocking + // the process, write() will transfer what it can and return the number of bytes written. + // Otherwise, it will return -1 and set errno to EAGAIN + if (errno == EAGAIN) + return true; + + closeChannel(&stdinChannel); + setErrorAndEmit(QProcess::WriteError); + return false; + } + stdinChannel.buffer.free(written); + if (!emittedBytesWritten && written != 0) { + emittedBytesWritten = true; + emit q_func()->bytesWritten(written); + emittedBytesWritten = false; + } + return true; } void QProcessPrivate::terminateProcess() diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 7e9cffe129..592bee58a5 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -787,17 +787,23 @@ qint64 QProcessPrivate::pipeWriterBytesToWrite() const return stdinChannel.writer ? stdinChannel.writer->bytesToWrite() : qint64(0); } -qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) +bool QProcessPrivate::writeToStdin() { Q_Q(QProcess); if (!stdinChannel.writer) { stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q); + QObject::connect(stdinChannel.writer, &QWindowsPipeWriter::bytesWritten, + q, &QProcess::bytesWritten); QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite, this, &QProcessPrivate::_q_canWrite); + } else { + if (stdinChannel.writer->isWriteOperationActive()) + return true; } - return stdinChannel.writer->write(data, maxlen); + stdinChannel.writer->write(stdinChannel.buffer.read()); + return true; } bool QProcessPrivate::waitForWrite(int msecs) diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp index 050d6879db..ab37a4c484 100644 --- a/src/corelib/io/qprocess_wince.cpp +++ b/src/corelib/io/qprocess_wince.cpp @@ -265,11 +265,9 @@ qint64 QProcessPrivate::pipeWriterBytesToWrite() const return 0; } -qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) +bool QProcessPrivate::writeToStdin() { - Q_UNUSED(data); - Q_UNUSED(maxlen); - return -1; + return false; } bool QProcessPrivate::waitForWrite(int msecs) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index ff92ca763e..05a4aa484a 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -73,21 +73,19 @@ QWindowsPipeWriter::~QWindowsPipeWriter() bool QWindowsPipeWriter::waitForWrite(int msecs) { - if (!writeSequenceStarted) - return false; - if (bytesWrittenPending) { - if (!inBytesWritten) - emitPendingBytesWrittenValue(); + emitPendingBytesWrittenValue(); return true; } + if (!writeSequenceStarted) + return false; + if (!waitForNotification(msecs)) return false; if (bytesWrittenPending) { - if (!inBytesWritten) - emitPendingBytesWrittenValue(); + emitPendingBytesWrittenValue(); return true; } @@ -96,20 +94,24 @@ bool QWindowsPipeWriter::waitForWrite(int msecs) qint64 QWindowsPipeWriter::bytesToWrite() const { - return numberOfBytesToWrite; + return numberOfBytesToWrite + pendingBytesWrittenValue; } void QWindowsPipeWriter::emitPendingBytesWrittenValue() { if (bytesWrittenPending) { + // Reset the state even if we don't emit bytesWritten(). + // It's a defined behavior to not re-emit this signal recursively. bytesWrittenPending = false; const qint64 bytes = pendingBytesWrittenValue; pendingBytesWrittenValue = 0; - inBytesWritten = true; - emit bytesWritten(bytes); - inBytesWritten = false; emit canWrite(); + if (!inBytesWritten) { + inBytesWritten = true; + emit bytesWritten(bytes); + inBytesWritten = false; + } } } @@ -129,6 +131,8 @@ void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten) notifiedCalled = true; writeSequenceStarted = false; numberOfBytesToWrite = 0; + Q_ASSERT(errorCode != ERROR_SUCCESS || numberOfBytesWritten == buffer.size()); + buffer.clear(); switch (errorCode) { case ERROR_SUCCESS: @@ -173,21 +177,26 @@ bool QWindowsPipeWriter::waitForNotification(int timeout) return notifiedCalled; } -qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) +bool QWindowsPipeWriter::write(const QByteArray &ba) { if (writeSequenceStarted) - return 0; + return false; overlapped.clear(); - numberOfBytesToWrite = maxlen; + buffer = ba; + numberOfBytesToWrite = buffer.size(); stopped = false; writeSequenceStarted = true; - if (!WriteFileEx(handle, ptr, maxlen, &overlapped, &writeFileCompleted)) { + if (!WriteFileEx(handle, buffer.constData(), numberOfBytesToWrite, + &overlapped, &writeFileCompleted)) { writeSequenceStarted = false; + numberOfBytesToWrite = 0; + buffer.clear(); qErrnoWarning("QWindowsPipeWriter::write failed."); + return false; } - return maxlen; + return true; } void QWindowsPipeWriter::stop() diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h index a78ab61adf..0228867522 100644 --- a/src/corelib/io/qwindowspipewriter_p.h +++ b/src/corelib/io/qwindowspipewriter_p.h @@ -47,6 +47,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -106,7 +107,7 @@ public: explicit QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent = 0); ~QWindowsPipeWriter(); - qint64 write(const char *data, qint64 maxlen); + bool write(const QByteArray &ba); void stop(); bool waitForWrite(int msecs); bool isWriteOperationActive() const { return writeSequenceStarted; } @@ -136,6 +137,7 @@ private: HANDLE handle; Overlapped overlapped; + QByteArray buffer; qint64 numberOfBytesToWrite; qint64 pendingBytesWrittenValue; bool stopped; diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h index 09828c8b0d..4b39a7c562 100644 --- a/src/network/socket/qlocalsocket.h +++ b/src/network/socket/qlocalsocket.h @@ -124,7 +124,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAbstractSocket::SocketState)) Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError)) #elif defined(Q_OS_WIN) - Q_PRIVATE_SLOT(d_func(), void _q_bytesWritten(qint64)) + Q_PRIVATE_SLOT(d_func(), void _q_canWrite()) Q_PRIVATE_SLOT(d_func(), void _q_pipeClosed()) Q_PRIVATE_SLOT(d_func(), void _q_winError(ulong, const QString &)) #else diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index a594605ae0..5e9a07be82 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -124,8 +124,7 @@ public: ~QLocalSocketPrivate(); void destroyPipeHandles(); void setErrorString(const QString &function); - void startNextWrite(); - void _q_bytesWritten(qint64 bytes); + void _q_canWrite(); void _q_pipeClosed(); void _q_winError(ulong windowsError, const QString &function); HANDLE handle; diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 4507c98835..99c8c77ed8 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -212,11 +212,12 @@ qint64 QLocalSocket::writeData(const char *data, qint64 len) memcpy(dest, data, len); if (!d->pipeWriter) { d->pipeWriter = new QWindowsPipeWriter(d->handle, this); - QObjectPrivate::connect(d->pipeWriter, &QWindowsPipeWriter::bytesWritten, - d, &QLocalSocketPrivate::_q_bytesWritten); + connect(d->pipeWriter, &QWindowsPipeWriter::bytesWritten, + this, &QLocalSocket::bytesWritten); + QObjectPrivate::connect(d->pipeWriter, &QWindowsPipeWriter::canWrite, + d, &QLocalSocketPrivate::_q_canWrite); } - if (!d->pipeWriter->isWriteOperationActive()) - d->startNextWrite(); + d->_q_canWrite(); return len; } @@ -269,7 +270,7 @@ qint64 QLocalSocket::bytesAvailable() const qint64 QLocalSocket::bytesToWrite() const { Q_D(const QLocalSocket); - return d->writeBuffer.size(); + return d->writeBuffer.size() + (d->pipeWriter ? d->pipeWriter->bytesToWrite() : 0); } bool QLocalSocket::canReadLine() const @@ -352,7 +353,7 @@ bool QLocalSocket::setSocketDescriptor(qintptr socketDescriptor, return true; } -void QLocalSocketPrivate::startNextWrite() +void QLocalSocketPrivate::_q_canWrite() { Q_Q(QLocalSocket); if (writeBuffer.isEmpty()) { @@ -360,18 +361,11 @@ void QLocalSocketPrivate::startNextWrite() q->close(); } else { Q_ASSERT(pipeWriter); - pipeWriter->write(writeBuffer.readPointer(), writeBuffer.nextDataBlockSize()); + if (!pipeWriter->isWriteOperationActive()) + pipeWriter->write(writeBuffer.read()); } } -void QLocalSocketPrivate::_q_bytesWritten(qint64 bytes) -{ - Q_Q(QLocalSocket); - writeBuffer.free(bytes); - startNextWrite(); - emit q->bytesWritten(bytes); -} - qintptr QLocalSocket::socketDescriptor() const { Q_D(const QLocalSocket); diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index 99f40ca215..6e55b15a18 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -78,6 +79,9 @@ private slots: void readBufferOverflow(); + void simpleCommandProtocol1(); + void simpleCommandProtocol2(); + void fullPath(); void hitMaximumConnections_data(); @@ -630,6 +634,110 @@ void tst_QLocalSocket::readBufferOverflow() QCOMPARE(client.bytesAvailable(), 0); } +static qint64 writeCommand(const QVariant &command, QIODevice *device, int commandCounter) +{ + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + out << qint64(0); + out << commandCounter; + out << command; + out.device()->seek(0); + out << qint64(block.size() - sizeof(qint64)); + return device->write(block); +} + +static QVariant readCommand(QIODevice *ioDevice, int *readCommandCounter, bool readSize = true) +{ + QDataStream in(ioDevice); + qint64 blockSize; + int commandCounter; + if (readSize) + in >> blockSize; + in >> commandCounter; + *readCommandCounter = commandCounter; + + QVariant command; + in >> command; + + return command; +} + +void tst_QLocalSocket::simpleCommandProtocol1() +{ + QLocalServer server; + server.listen(QStringLiteral("simpleProtocol")); + + QLocalSocket localSocketWrite; + localSocketWrite.connectToServer(server.serverName()); + QVERIFY(server.waitForNewConnection()); + QLocalSocket *localSocketRead = server.nextPendingConnection(); + QVERIFY(localSocketRead); + + int readCounter = 0; + for (int i = 0; i < 2000; ++i) { + const QVariant command(QRect(readCounter, i, 10, 10)); + const qint64 blockSize = writeCommand(command, &localSocketWrite, i); + while (localSocketWrite.bytesToWrite()) + QVERIFY(localSocketWrite.waitForBytesWritten()); + while (localSocketRead->bytesAvailable() < blockSize) { + QVERIFY(localSocketRead->waitForReadyRead(1000)); + } + const QVariant variant = readCommand(localSocketRead, &readCounter); + QCOMPARE(readCounter, i); + QCOMPARE(variant, command); + } +} + +void tst_QLocalSocket::simpleCommandProtocol2() +{ + QLocalServer server; + server.listen(QStringLiteral("simpleProtocol")); + + QLocalSocket localSocketWrite; + localSocketWrite.connectToServer(server.serverName()); + QVERIFY(server.waitForNewConnection()); + QLocalSocket* localSocketRead = server.nextPendingConnection(); + QVERIFY(localSocketRead); + + int readCounter = 0; + qint64 writtenBlockSize = 0; + qint64 blockSize = 0; + + QObject::connect(localSocketRead, &QLocalSocket::readyRead, [&] { + forever { + if (localSocketRead->bytesAvailable() < sizeof(qint64)) + return; + + if (blockSize == 0) { + QDataStream in(localSocketRead); + in >> blockSize; + } + + if (localSocketRead->bytesAvailable() < blockSize) + return; + + int commandNumber = 0; + const QVariant variant = readCommand(localSocketRead, &commandNumber, false); + QCOMPARE(writtenBlockSize, blockSize); + QCOMPARE(readCounter, commandNumber); + QCOMPARE(variant.userType(), (int)QMetaType::QRect); + + readCounter++; + blockSize = 0; + } + }); + + for (int i = 0; i < 500; ++i) { + const QVariant command(QRect(readCounter, i, 10, 10)); + writtenBlockSize = writeCommand(command, &localSocketWrite, i) - sizeof(qint64); + if (i % 10 == 0) + QTest::qWait(1); + } + + localSocketWrite.abort(); + QVERIFY(localSocketRead->waitForDisconnected(1000)); +} + // QLocalSocket/Server can take a name or path, check that it works as expected void tst_QLocalSocket::fullPath() { -- cgit v1.2.3 From 54d95d09887e9f6394dcc440369959994ff5bad9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 29 Apr 2016 11:27:11 +0200 Subject: Fix UB (data race) in Q_GLOBAL_STATIC The store to guard in the inner function's critical section was not synchronized-with the load at the start of the function: T1 T2 guard.load() mutex.lock() guard.load() d = new Type guard.store() guard.load() // use d mutex.unlock() The use of d in T2 does not synchronize with the write to d in T1 -> data race -> UB. Fix by storing with release memory ordering, so that the guard.load() in T2 synchronizes with the guard.store() in T1. Change-Id: I5c1cd1fa097c6397cb0b48b0d8e8012f95978558 Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/global/qglobalstatic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h index 41fc151652..22194d8be7 100644 --- a/src/corelib/global/qglobalstatic.h +++ b/src/corelib/global/qglobalstatic.h @@ -110,7 +110,7 @@ QT_BEGIN_NAMESPACE guard.store(QtGlobalStatic::Destroyed); \ } \ } cleanup; \ - guard.store(QtGlobalStatic::Initialized); \ + guard.storeRelease(QtGlobalStatic::Initialized); \ } \ } \ return d; \ -- cgit v1.2.3 From c6d041e7ca3eb7945bf143a5c4fffcb2b2afba75 Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Sun, 1 May 2016 14:31:48 +0200 Subject: xcb: Fix drag and drop to Emacs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unfortunately, the improved patch for QTBUG-45812 fixed things for Chromium, but did no longer work for Emacs. This fixes commit [269fdb] to make it work for both Emacs and Chromium. Task-number: QTBUG-45812 Change-Id: I2fca708503f27679681bc6959de1ad94943a063e Reviewed-by: Dmitry Shachnev Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbdrag.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index f1428d0a96..529f91e1ec 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1134,10 +1134,10 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event at = findTransactionByWindow(event->requestor); } - if (at == -1 && event->time == XCB_CURRENT_TIME) { + if (at == -1) { xcb_window_t target = findXdndAwareParent(connection(), event->requestor); if (target) { - if (current_target == target) + if (event->time == XCB_CURRENT_TIME && current_target == target) at = -2; else at = findTransactionByWindow(target); -- cgit v1.2.3 From c09008d27ca1456fb53a3fc9c71d5f88b1081221 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 2 May 2016 11:34:44 +0200 Subject: QWindowsPipeWriter: Fix developer build with MinGW. Fix signedness in comparion: io\qwindowspipewriter.cpp: In member function 'void QWindowsPipeWriter::notified(DWORD, DWORD)': io\qwindowspipewriter.cpp:134:65: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] Q_ASSERT(errorCode != ERROR_SUCCESS || numberOfBytesWritten == buffer.size()); Amends change a4d26cf522b966056e47e47a004b7e4d668e3a2d. Task-number: QTBUG-52401 Change-Id: If0c0e2107342408675fa00b93f28c9de339080f6 Reviewed-by: Joerg Bornemann --- src/corelib/io/qwindowspipewriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index 05a4aa484a..839dc8a19c 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -131,7 +131,7 @@ void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten) notifiedCalled = true; writeSequenceStarted = false; numberOfBytesToWrite = 0; - Q_ASSERT(errorCode != ERROR_SUCCESS || numberOfBytesWritten == buffer.size()); + Q_ASSERT(errorCode != ERROR_SUCCESS || numberOfBytesWritten == DWORD(buffer.size())); buffer.clear(); switch (errorCode) { -- cgit v1.2.3 From 1c456751b35ded269663d63015b8078bab283b93 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 27 Apr 2016 18:40:56 +0300 Subject: Fix QFile::copy() on WinRT. Implementation of QFileSystemEngine::copyFile() uses CopyFile2() as if it is CopyFile() function, but CopyFile2() returns HRESULT, not BOOL. So the success should be checked by "SUCCEEDED()" instead of "!= 0". Current implementation does exactly the opposite because S_OK == 0. Change-Id: I0677d54447d22366fb2031e0b928a3d10e24c0ed Reviewed-by: Maurice Kalinowski --- src/corelib/io/qfilesystemengine_win.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index f1a6019094..e55ab0b544 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -1416,8 +1416,9 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst COPYFILE2_EXTENDED_PARAMETERS copyParams = { sizeof(copyParams), COPY_FILE_FAIL_IF_EXISTS, NULL, NULL, NULL }; - bool ret = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(), - (const wchar_t*)target.nativeFilePath().utf16(), ©Params) != 0; + HRESULT hres = ::CopyFile2((const wchar_t*)source.nativeFilePath().utf16(), + (const wchar_t*)target.nativeFilePath().utf16(), ©Params); + bool ret = SUCCEEDED(hres); #endif // Q_OS_WINRT if(!ret) error = QSystemError(::GetLastError(), QSystemError::NativeError); -- cgit v1.2.3 From 63169fc893973437696ad49c4e3dfdd28e356f37 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 28 Apr 2016 13:28:51 +0200 Subject: Fix underline position on Liberation Mono Ensure we don't round a underline position beyond the descent in our eagerness to avoid underlines too close to baseline. Task-number: QTCREATORBUG-15851 Change-Id: I9a29447bbcb938b7e9fb29d52fd392a1340d07c5 Reviewed-by: Konstantin Ritt Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/painting/qpainter.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index baeee4dbfa..62254213f3 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6251,9 +6251,6 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->setRenderHint(QPainter::Qt4CompatiblePainting, false); const qreal underlineOffset = fe->underlinePosition().toReal(); - // deliberately ceil the offset to avoid the underline coming too close to - // the text above it. - const qreal underlinePos = pos.y() + qCeil(underlineOffset) + 0.5; if (underlineStyle == QTextCharFormat::SpellCheckUnderline) { QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); @@ -6278,6 +6275,12 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave); painter->restore(); } else if (underlineStyle != QTextCharFormat::NoUnderline) { + // Deliberately ceil the offset to avoid the underline coming too close to + // the text above it, but limit it to stay within descent. + qreal adjustedUnderlineOffset = std::ceil(underlineOffset) + 0.5; + if (underlineOffset <= fe->descent().toReal()) + adjustedUnderlineOffset = qMin(adjustedUnderlineOffset, fe->descent().toReal() - 0.5); + const qreal underlinePos = pos.y() + adjustedUnderlineOffset; QColor uc = charFormat.underlineColor(); if (uc.isValid()) pen.setColor(uc); -- cgit v1.2.3 From 8badbd5040fd41ad258d90edacb7b28b9a0ef870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 26 Apr 2016 17:38:55 +0200 Subject: iOS: Report correct physicalSize and physicalDotsPerInch for iPhone6+ On iPhone 6(s) Plus devices, or when display zoom is enabled in an iPhone 6, the render buffer is scaled before being output on the physical display. We have to take this into account when computing the physical size. Task-number: QTBUG-50941 Change-Id: I318f3a866d039fccf0ba08f381fc9d8bcd676acd Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosscreen.h | 2 +- src/plugins/platforms/ios/qiosscreen.mm | 27 +++++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index f31be9756c..d6627c78cb 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -73,7 +73,7 @@ private: QRect m_geometry; QRect m_availableGeometry; int m_depth; - uint m_pixelDensity; + uint m_physicalDpi; QSizeF m_physicalSize; QIOSOrientationListener *m_orientationListener; }; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 5cb06d591d..d9ec7008d3 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -180,18 +180,18 @@ QIOSScreen::QIOSScreen(UIScreen *screen) if (deviceIdentifier.contains(QRegularExpression("^iPhone(7,1|8,2)$"))) { // iPhone 6 Plus or iPhone 6S Plus - m_pixelDensity = 401; + m_physicalDpi = 401; } else if (deviceIdentifier.contains(QRegularExpression("^iPad(1,1|2,[1-4]|3,[1-6]|4,[1-3]|5,[3-4]|6,[7-8])$"))) { // All iPads except the iPad Mini series - m_pixelDensity = 132 * devicePixelRatio(); + m_physicalDpi = 132 * devicePixelRatio(); } else { // All non-Plus iPhones, and iPad Minis - m_pixelDensity = 163 * devicePixelRatio(); + m_physicalDpi = 163 * devicePixelRatio(); } } else { // External display, hard to say m_depth = 24; - m_pixelDensity = 96; + m_physicalDpi = 96; } for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) { @@ -253,8 +253,23 @@ void QIOSScreen::updateProperties() } if (m_geometry != previousGeometry) { - const qreal millimetersPerInch = 25.4; - m_physicalSize = QSizeF(m_geometry.size() * devicePixelRatio()) / m_pixelDensity * millimetersPerInch; + QRectF physicalGeometry; + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { + // We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet + Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ? + Qt::LandscapeOrientation : Qt::PortraitOrientation; + + // On iPhone 6+ devices, or when display zoom is enabled, the render buffer is scaled + // before being output on the physical display. We have to take this into account when + // computing the physical size. Note that unlike the native bounds, the physical size + // follows the primary orientation of the screen. + physicalGeometry = mapBetween(nativeOrientation(), primaryOrientation, fromCGRect(m_uiScreen.nativeBounds).toRect()); + } else { + physicalGeometry = QRectF(0, 0, m_geometry.width() * devicePixelRatio(), m_geometry.height() * devicePixelRatio()); + } + + static const qreal millimetersPerInch = 25.4; + m_physicalSize = physicalGeometry.size() / m_physicalDpi * millimetersPerInch; } // At construction time, we don't yet have an associated QScreen, but we still want -- cgit v1.2.3 From 9af2cccc597fd094de34c83d742803c5f4c0a8d6 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Mon, 2 May 2016 17:54:50 +0300 Subject: QNativeSocketEngine: fix build in debug mode under Windows Change-Id: Id9b42f3d40b82ae6a8d581b0fbf6fd0b2ae589aa Reviewed-by: Timur Pocheptsov --- src/network/socket/qnativesocketengine_win.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 7b6be9ebf9..770bae7bf3 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1177,7 +1177,7 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const #endif #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %li", ret); + qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %lli", ret); #endif return ret; @@ -1283,10 +1283,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li", + bool printSender = (ret != -1 && (options & QNativeSocketEngine::WantDatagramSender) != 0); + qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", data, qt_prettyDebug(data, qMin(ret, 16), ret).data(), maxLength, - address ? address->toString().toLatin1().constData() : "(nil)", - port ? *port : 0, ret); + printSender ? header->senderAddress.toString().toLatin1().constData() : "(unknown)", + printSender ? header->senderPort : 0, ret); #endif return ret; @@ -1398,9 +1399,10 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l } #if defined (QNATIVESOCKETENGINE_DEBUG) - qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data, - qt_prettyDebug(data, qMin(len, 16), len).data(), 0, address.toString().toLatin1().constData(), - port, ret); + qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, + qt_prettyDebug(data, qMin(len, 16), len).data(), len, + header.destinationAddress.toString().toLatin1().constData(), + header.destinationPort, ret); #endif return ret; -- cgit v1.2.3 From be6a92ec0920491a68e747b48154ad8712d97f4b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 22 Apr 2016 20:20:47 +0200 Subject: remove redundant OTHER_FILES assignments newer versions of qt creator understand QMAKE_EXTRA_COMPILERS and INSTALLS, so there is no need to list the files twice. Change-Id: Iccf3cc3248daf3422b8c366c2eb2d2f46c5f08d1 Reviewed-by: Joerg Bornemann --- mkspecs/features/qml_module.prf | 3 --- src/plugins/bearer/android/jar/jar.pri | 2 -- tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro | 1 - tests/manual/textrendering/glyphshaping/glyphshaping.pro | 1 - 4 files changed, 7 deletions(-) diff --git a/mkspecs/features/qml_module.prf b/mkspecs/features/qml_module.prf index 9e136a49f2..b09d42a0a4 100644 --- a/mkspecs/features/qml_module.prf +++ b/mkspecs/features/qml_module.prf @@ -17,9 +17,6 @@ fq_qml_files = $$_PRO_FILE_PWD_/qmldir for(qmlf, QML_FILES): fq_qml_files += $$absolute_path($$qmlf, $$_PRO_FILE_PWD_) -# Only for Qt Creator's project view -OTHER_FILES += $$fq_qml_files - qml1_target: \ instbase = $$[QT_INSTALL_IMPORTS] else: \ diff --git a/src/plugins/bearer/android/jar/jar.pri b/src/plugins/bearer/android/jar/jar.pri index 6d9aac3bb3..e43dbf0711 100644 --- a/src/plugins/bearer/android/jar/jar.pri +++ b/src/plugins/bearer/android/jar/jar.pri @@ -9,5 +9,3 @@ JAVASOURCES += $$PWD/src/org/qtproject/qt5/android/bearer/QtNetworkReceiver.java # install target.path = $$[QT_INSTALL_PREFIX]/jar INSTALLS += target - -OTHER_FILES += $$JAVASOURCES diff --git a/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro b/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro index a311173c0e..f03ac49c5d 100644 --- a/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro +++ b/tests/auto/corelib/io/qloggingregistry/qloggingregistry.pro @@ -5,7 +5,6 @@ CONFIG += testcase QT = core core-private testlib SOURCES += tst_qloggingregistry.cpp -OTHER_FILES += qtlogging.ini TESTDATA += qtlogging.ini android:!android-no-sdk: { diff --git a/tests/manual/textrendering/glyphshaping/glyphshaping.pro b/tests/manual/textrendering/glyphshaping/glyphshaping.pro index 5dc8542e86..4fef879c9c 100644 --- a/tests/manual/textrendering/glyphshaping/glyphshaping.pro +++ b/tests/manual/textrendering/glyphshaping/glyphshaping.pro @@ -1,6 +1,5 @@ QT += widgets SOURCES = main.cpp -OTHER_FILES = glyphshaping_data.xml glyphshaping_data.path = . glyphshaping_data.files = $$PWD/glyphshaping_data.xml DEPLOYMENT += glyphshaping_data -- cgit v1.2.3 From ce044ce3482b5abc85ecaf42842df1d4a5ad7806 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 29 Apr 2016 11:38:08 +0200 Subject: ensure that QMAKE_FILE_{IN,OUT}_BASE are quoted it's beyond me why they shouldn't be. Change-Id: I2493469636e4f196bfeb2eb00a691aeae0f1881d Reviewed-by: Joerg Bornemann --- qmake/generators/makefile.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 5ec4cfb7ef..66d0b91d61 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1611,7 +1611,7 @@ MakefileGenerator::replaceExtraCompilerVariables( const ProKey funcname = var.mid(19).toKey(); val += project->expand(funcname, QList() << ProStringList(in)); } else if(var == QLatin1String("QMAKE_FILE_BASE") || var == QLatin1String("QMAKE_FILE_IN_BASE")) { - //filePath = true; + filePath = true; for(int i = 0; i < in.size(); ++i) { QFileInfo fi(fileInfo(Option::normalizePath(in.at(i)))); QString base = fi.completeBaseName(); @@ -1653,7 +1653,7 @@ MakefileGenerator::replaceExtraCompilerVariables( for(int i = 0; i < out.size(); ++i) val += fileInfo(Option::normalizePath(out.at(i))).filePath(); } else if(var == QLatin1String("QMAKE_FILE_OUT_BASE")) { - //filePath = true; + filePath = true; for(int i = 0; i < out.size(); ++i) { QFileInfo fi(fileInfo(Option::normalizePath(out.at(i)))); QString base = fi.completeBaseName(); -- cgit v1.2.3 From 49f92f9ab75f5fcc086543d9dbcc025c37677715 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 29 Apr 2016 11:34:14 +0200 Subject: add some missing filename expandos to extra compilers - QMAKE_FILE_IN_EXT as an alias for QMAKE_FILE_EXT, for consistency with QMAKE_FILE_IN_BASE - QMAKE_FILE_IN_NAME to make pairing _EXT/_BASE to get a full name unnecessary (finally ...), and make use of it - QMAKE_FILE_OUT_PATH, because i'll need it Change-Id: I3d91ddb84f9cce52a665d562da11d165c92550c8 Reviewed-by: Joerg Bornemann --- mkspecs/features/file_copies.prf | 2 +- qmake/generators/makefile.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/file_copies.prf b/mkspecs/features/file_copies.prf index f679129e03..04a02258d5 100644 --- a/mkspecs/features/file_copies.prf +++ b/mkspecs/features/file_copies.prf @@ -24,7 +24,7 @@ for (cp, COPIES) { isEmpty(path): error("COPY $cp defines no .path") base = $$eval($${cp}.base) isEmpty(base) { - $${pfx}.output = $$path/${QMAKE_FILE_BASE}${QMAKE_FILE_EXT} + $${pfx}.output = $$path/${QMAKE_FILE_IN_NAME} } else: isEqual(base, $$_PRO_FILE_PWD_) { $${pfx}.output = $$path/${QMAKE_FUNC_FILE_IN_qtStripProPwd} } else { diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 66d0b91d61..a596474669 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -1619,7 +1619,7 @@ MakefileGenerator::replaceExtraCompilerVariables( base = fi.fileName(); val += base; } - } else if(var == QLatin1String("QMAKE_FILE_EXT")) { + } else if (var == QLatin1String("QMAKE_FILE_EXT") || var == QLatin1String("QMAKE_FILE_IN_EXT")) { filePath = true; for(int i = 0; i < in.size(); ++i) { QFileInfo fi(fileInfo(Option::normalizePath(in.at(i)))); @@ -1632,6 +1632,10 @@ MakefileGenerator::replaceExtraCompilerVariables( ext = fi.fileName().remove(0, baseLen); val += ext; } + } else if (var == QLatin1String("QMAKE_FILE_IN_NAME")) { + filePath = true; + for (int i = 0; i < in.size(); ++i) + val += fileInfo(Option::normalizePath(in.at(i))).fileName(); } else if(var == QLatin1String("QMAKE_FILE_PATH") || var == QLatin1String("QMAKE_FILE_IN_PATH")) { filePath = true; for(int i = 0; i < in.size(); ++i) @@ -1648,6 +1652,10 @@ MakefileGenerator::replaceExtraCompilerVariables( filePath = true; const ProKey funcname = var.mid(20).toKey(); val += project->expand(funcname, QList() << ProStringList(out)); + } else if (var == QLatin1String("QMAKE_FILE_OUT_PATH")) { + filePath = true; + for (int i = 0; i < out.size(); ++i) + val += fileInfo(Option::normalizePath(out.at(i))).path(); } else if(var == QLatin1String("QMAKE_FILE_OUT")) { filePath = true; for(int i = 0; i < out.size(); ++i) -- cgit v1.2.3 From 8f0bf2d3d258acfae91e7dda2d1e7ad29b950c9b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 29 Apr 2016 11:36:15 +0200 Subject: support directories in COPIES this makes it fully consistent with INSTALLS. note that this also removes the file name from the target path when copying files, also for consistency. Change-Id: I69042c9aa1e2cc81f8ff982343ba25688a04abfd Reviewed-by: Joerg Bornemann --- mkspecs/features/file_copies.prf | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/mkspecs/features/file_copies.prf b/mkspecs/features/file_copies.prf index 04a02258d5..6df294212c 100644 --- a/mkspecs/features/file_copies.prf +++ b/mkspecs/features/file_copies.prf @@ -18,10 +18,21 @@ defineReplace(qtStripProPwd) { for (cp, COPIES) { isEmpty($${cp}.files): next() pfx = copy_$${cp} - for (f, $${cp}.files): \ - $${pfx}.files += $$absolute_path($$f, $$_PRO_FILE_PWD_) + notdir = false + dir = false + for (f, $${cp}.files) { + fil = $$absolute_path($$f, $$_PRO_FILE_PWD_) + tfiles = $$files($$fil/*) + isEmpty(tfiles): \ + notdir = true + else: \ + dir = true + $${pfx}.files += $$fil + } + $$dir:$$notdir: \ + error("COPIES entry $$cp lists both files and directories.") path = $$eval($${cp}.path) - isEmpty(path): error("COPY $cp defines no .path") + isEmpty(path): error("COPIES entry $$cp defines no .path") base = $$eval($${cp}.base) isEmpty(base) { $${pfx}.output = $$path/${QMAKE_FILE_IN_NAME} @@ -34,7 +45,12 @@ for (cp, COPIES) { $${pfx}.output = $$path/${QMAKE_FUNC_FILE_IN_qtStripSrcDir_$$cp} } $${pfx}.input = $${pfx}.files - $${pfx}.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} + !$$dir: \ + $${pfx}.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT_PATH} + else: !copy_dir_files: \ + $${pfx}.commands = $$QMAKE_COPY_DIR ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT_PATH} + else: \ + $${pfx}.commands = $$QMAKE_COPY_DIR ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} $${pfx}.name = COPY ${QMAKE_FILE_IN} $${pfx}.CONFIG = no_link no_clean target_predeps QMAKE_EXTRA_COMPILERS += $${pfx} -- cgit v1.2.3 From 22a7edd816b417daf43e3b4c4f0257fbc3ad7921 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 7 Apr 2016 14:18:21 +0200 Subject: tst_QTcpSocket, tst_QUdpSocket: Improve diagnostics. Add more error messages on failures. Task-number: QTBUG-25367 Task-number: QTBUG-25368 Change-Id: I064143a058b7b98d9d5eecab8b5da49f5307e1eb Reviewed-by: Edward Welbourne Reviewed-by: Richard J. Moore --- tests/auto/network-settings.h | 20 ++++++++++- .../network/socket/qtcpsocket/tst_qtcpsocket.cpp | 6 ++-- .../network/socket/qudpsocket/tst_qudpsocket.cpp | 40 +++++++++++----------- .../network/socket/qudpsocket/udpServer/main.cpp | 30 +++++++++++----- 4 files changed, 65 insertions(+), 31 deletions(-) diff --git a/tests/auto/network-settings.h b/tests/auto/network-settings.h index a90ea62277..f4ec460709 100644 --- a/tests/auto/network-settings.h +++ b/tests/auto/network-settings.h @@ -34,6 +34,8 @@ #include #ifdef QT_NETWORK_LIB #include +#include +#include #endif #ifdef Q_OS_UNIX @@ -139,5 +141,21 @@ public: } return true; } -#endif + + // Helper function for usage with QVERIFY2 on sockets. + static QByteArray msgSocketError(const QAbstractSocket &s) + { + QString result; + QDebug debug(&result); + debug.nospace(); + debug.noquote(); + if (!s.localAddress().isNull()) + debug << "local=" << s.localAddress().toString() << ':' << s.localPort(); + if (!s.peerAddress().isNull()) + debug << ", peer=" << s.peerAddress().toString() << ':' << s.peerPort(); + debug << ", type=" << s.socketType() << ", state=" << s.state() + << ", error=" << s.error() << ": " << s.errorString(); + return result.toLocal8Bit(); + } +#endif // QT_NETWORK_LIB }; diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index cde453c191..bdfb7d2fb8 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -675,8 +675,10 @@ void tst_QTcpSocket::bindThenResolveHost() dummySocket.close(); - socket->connectToHost(hostName, 80); - QVERIFY2(socket->waitForConnected(), "Network timeout"); + const quint16 port = 80; + socket->connectToHost(hostName, port); + QVERIFY2(socket->waitForConnected(), (hostName.toLocal8Bit() + ": " + QByteArray::number(port) + ' ' + + QtNetworkSettings::msgSocketError(*socket)).constData()); QCOMPARE(socket->localPort(), boundPort); QCOMPARE(socket->socketDescriptor(), fd); diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 0ee3255502..7ab8f6d3cc 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -265,7 +266,7 @@ void tst_QUdpSocket::unconnectedServerAndClientTest() char buf[1024]; QHostAddress host; quint16 port; - QVERIFY(serverSocket.waitForReadyRead(5000)); + QVERIFY2(serverSocket.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(serverSocket).constData()); QCOMPARE(int(serverSocket.readDatagram(buf, sizeof(buf), &host, &port)), int(strlen(message[i]))); buf[strlen(message[i])] = '\0'; @@ -397,8 +398,8 @@ void tst_QUdpSocket::loop() QCOMPARE(paul.writeDatagram(paulMessage.data(), paulMessage.length(), peterAddress, peter.localPort()), qint64(paulMessage.length())); - QVERIFY(peter.waitForReadyRead(9000)); - QVERIFY(paul.waitForReadyRead(9000)); + QVERIFY2(peter.waitForReadyRead(9000), QtNetworkSettings::msgSocketError(peter).constData()); + QVERIFY2(paul.waitForReadyRead(9000), QtNetworkSettings::msgSocketError(paul).constData()); char peterBuffer[16*1024]; char paulBuffer[16*1024]; if (success) { @@ -454,8 +455,8 @@ void tst_QUdpSocket::ipv6Loop() char peterBuffer[16*1024]; char paulBuffer[16*1024]; #if !defined(Q_OS_WINCE) - QVERIFY(peter.waitForReadyRead(5000)); - QVERIFY(paul.waitForReadyRead(5000)); + QVERIFY2(peter.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(peter).constData()); + QVERIFY2(paul.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(paul).constData()); #else QVERIFY(peter.waitForReadyRead(15000)); QVERIFY(paul.waitForReadyRead(15000)); @@ -490,7 +491,7 @@ void tst_QUdpSocket::dualStack() QByteArray buffer; //test v4 -> dual QCOMPARE((int)v4Sock.writeDatagram(v4Data.constData(), v4Data.length(), QHostAddress(QHostAddress::LocalHost), dualSock.localPort()), v4Data.length()); - QVERIFY(dualSock.waitForReadyRead(5000)); + QVERIFY2(dualSock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(dualSock).constData()); buffer.reserve(100); qint64 size = dualSock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, v4Data.length()); @@ -504,7 +505,7 @@ void tst_QUdpSocket::dualStack() //test v6 -> dual QCOMPARE((int)v6Sock.writeDatagram(v6Data.constData(), v6Data.length(), QHostAddress(QHostAddress::LocalHostIPv6), dualSock.localPort()), v6Data.length()); - QVERIFY(dualSock.waitForReadyRead(5000)); + QVERIFY2(dualSock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(dualSock).constData()); buffer.reserve(100); size = dualSock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, v6Data.length()); @@ -513,7 +514,7 @@ void tst_QUdpSocket::dualStack() //test dual -> v6 QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length()); - QVERIFY(v6Sock.waitForReadyRead(5000)); + QVERIFY2(v6Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v6Sock).constData()); buffer.reserve(100); size = v6Sock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, dualData.length()); @@ -523,7 +524,7 @@ void tst_QUdpSocket::dualStack() //test dual -> v4 QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length()); - QVERIFY(v4Sock.waitForReadyRead(5000)); + QVERIFY2(v4Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v4Sock).constData()); buffer.reserve(100); size = v4Sock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, dualData.length()); @@ -555,7 +556,7 @@ void tst_QUdpSocket::dualStackAutoBinding() QUdpSocket dualSock; QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length()); - QVERIFY(v4Sock.waitForReadyRead(5000)); + QVERIFY2(v4Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v4Sock).constData()); buffer.reserve(100); size = v4Sock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, dualData.length()); @@ -563,7 +564,7 @@ void tst_QUdpSocket::dualStackAutoBinding() QCOMPARE(buffer, dualData); QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length()); - QVERIFY(v6Sock.waitForReadyRead(5000)); + QVERIFY2(v6Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v6Sock).constData()); buffer.reserve(100); size = v6Sock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, dualData.length()); @@ -576,7 +577,7 @@ void tst_QUdpSocket::dualStackAutoBinding() QUdpSocket dualSock; QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length()); - QVERIFY(v6Sock.waitForReadyRead(5000)); + QVERIFY2(v6Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v6Sock).constData()); buffer.reserve(100); size = v6Sock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, dualData.length()); @@ -584,7 +585,7 @@ void tst_QUdpSocket::dualStackAutoBinding() QCOMPARE(buffer, dualData); QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length()); - QVERIFY(v4Sock.waitForReadyRead(5000)); + QVERIFY2(v4Sock.waitForReadyRead(5000), QtNetworkSettings::msgSocketError(v4Sock).constData()); buffer.reserve(100); size = v4Sock.readDatagram(buffer.data(), 100, &from, &port); QCOMPARE((int)size, dualData.length()); @@ -689,7 +690,7 @@ void tst_QUdpSocket::pendingDatagramSize() QVERIFY(client.writeDatagram("3 messages", 10, serverAddress, server.localPort()) == 10); char c = 0; - QVERIFY(server.waitForReadyRead()); + QVERIFY2(server.waitForReadyRead(), QtNetworkSettings::msgSocketError(server).constData()); if (server.hasPendingDatagrams()) { #if defined Q_OS_HPUX && defined __ia64 QEXPECT_FAIL("", "HP-UX 11i v2 can't determine the datagram size correctly.", Abort); @@ -1101,7 +1102,7 @@ void tst_QUdpSocket::zeroLengthDatagram() #endif QCOMPARE(sender.writeDatagram(QByteArray(), QHostAddress::LocalHost, receiver.localPort()), qint64(0)); - QVERIFY(receiver.waitForReadyRead(1000)); + QVERIFY2(receiver.waitForReadyRead(1000), QtNetworkSettings::msgSocketError(receiver).constData()); QVERIFY(receiver.hasPendingDatagrams()); char buf; @@ -1379,8 +1380,7 @@ void tst_QUdpSocket::multicast() int(datagram.size())); } - QVERIFY2(receiver.waitForReadyRead(), - qPrintable(receiver.errorString())); + QVERIFY2(receiver.waitForReadyRead(), QtNetworkSettings::msgSocketError(receiver).constData()); QVERIFY(receiver.hasPendingDatagrams()); QList receivedDatagrams; while (receiver.hasPendingDatagrams()) { @@ -1446,7 +1446,7 @@ void tst_QUdpSocket::echo() qDebug() << "packets in" << successes << "out" << i; QTest::qWait(50); //choke to avoid triggering flood/DDoS protections on echo service } - QVERIFY(successes >= 9); + QVERIFY2(successes >= 9, QByteArray::number(successes).constData()); } void tst_QUdpSocket::linkLocalIPv6() @@ -1567,7 +1567,7 @@ void tst_QUdpSocket::linkLocalIPv4() QByteArray receiveBuffer("xxxxx"); foreach (QUdpSocket *s, sockets) { QVERIFY(s->writeDatagram(testData, s->localAddress(), neutral.localPort())); - QVERIFY(neutral.waitForReadyRead(10000)); + QVERIFY2(neutral.waitForReadyRead(10000), QtNetworkSettings::msgSocketError(neutral).constData()); QHostAddress from; quint16 fromPort; QCOMPARE((int)neutral.readDatagram(receiveBuffer.data(), receiveBuffer.length(), &from, &fromPort), testData.length()); @@ -1576,7 +1576,7 @@ void tst_QUdpSocket::linkLocalIPv4() QCOMPARE(receiveBuffer, testData); QVERIFY(neutral.writeDatagram(testData, s->localAddress(), s->localPort())); - QVERIFY(s->waitForReadyRead(10000)); + QVERIFY2(s->waitForReadyRead(10000), QtNetworkSettings::msgSocketError(*s).constData()); QCOMPARE((int)s->readDatagram(receiveBuffer.data(), receiveBuffer.length(), &from, &fromPort), testData.length()); QCOMPARE(receiveBuffer, testData); diff --git a/tests/auto/network/socket/qudpsocket/udpServer/main.cpp b/tests/auto/network/socket/qudpsocket/udpServer/main.cpp index 2562e58862..f393c26329 100644 --- a/tests/auto/network/socket/qudpsocket/udpServer/main.cpp +++ b/tests/auto/network/socket/qudpsocket/udpServer/main.cpp @@ -36,18 +36,21 @@ class Server : public QObject { Q_OBJECT public: - Server(int port) + + Server() { connect(&serverSocket, &QIODevice::readyRead, this, &Server::sendEcho); } + + bool bind(quint16 port) { - connect(&serverSocket, SIGNAL(readyRead()), - this, SLOT(sendEcho())); - if (serverSocket.bind(QHostAddress::Any, port, - QUdpSocket::ReuseAddressHint - | QUdpSocket::ShareAddress)) { + const bool result = serverSocket.bind(QHostAddress::Any, port, + QUdpSocket::ReuseAddressHint + | QUdpSocket::ShareAddress); + if (result) { printf("OK\n"); } else { - printf("FAILED\n"); + printf("FAILED: %s\n", qPrintable(serverSocket.errorString())); } fflush(stdout); + return result; } private slots: @@ -73,8 +76,19 @@ private: int main(int argc, char **argv) { QCoreApplication app(argc, argv); + QStringList arguments = QCoreApplication::arguments(); + arguments.pop_front(); + quint16 port = 0; + if (!arguments.isEmpty()) + port = arguments.constFirst().toUShort(); + if (!port) { + printf("Specify port number\n"); + return -1; + } - Server server(app.arguments().at(1).toInt()); + Server server; + if (!server.bind(port)) + return -2; return app.exec(); } -- cgit v1.2.3 From fecaa6aae83a3ffa8f1fd41c5aa8275a1bfa7c9b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 27 Apr 2016 23:44:57 -0700 Subject: Workaround Windows DLL unload issue with threads running We don't know why it happens, so let's apply a workaround. See the comment for more details. Task-number: QTBUG-53031 Change-Id: Ifea6e497f11a461db432ffff144972e892fbbda5 Reviewed-by: Roland Winklmeier Reviewed-by: Friedemann Kleint Reviewed-by: Maurice Kalinowski Reviewed-by: Thiago Macieira --- src/dbus/qdbusconnection.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 34b3da7df3..7cdacc1284 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -62,6 +62,10 @@ QT_BEGIN_NAMESPACE +#ifdef Q_OS_WIN +static void preventDllUnload(); +#endif + Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) // can be replaced with a lambda in Qt 5.7 @@ -150,6 +154,10 @@ QDBusConnectionManager::QDBusConnectionManager() this, &QDBusConnectionManager::createServer, Qt::BlockingQueuedConnection); moveToThread(this); // ugly, don't do this in other projects +#ifdef Q_OS_WIN + // prevent the library from being unloaded on Windows. See comments in the function. + preventDllUnload(); +#endif defaultBuses[0] = defaultBuses[1] = Q_NULLPTR; start(); } @@ -1275,4 +1283,31 @@ QT_END_NAMESPACE #include "qdbusconnection.moc" +#ifdef Q_OS_WIN +# include + +QT_BEGIN_NAMESPACE +static void preventDllUnload() +{ + // Thread termination is really wacky on Windows. For some reason we don't + // understand, exiting from the thread may try to unload the DLL. Since the + // QDBusConnectionManager thread runs until the DLL is unloaded, we've got + // a deadlock: the main thread is waiting for the manager thread to exit, + // but the manager thread is attempting to acquire a lock to unload the DLL. + // + // We work around the issue by preventing the unload from happening in the + // first place. + // + // For this trick, see + // https://blogs.msdn.microsoft.com/oldnewthing/20131105-00/?p=2733 + + static HMODULE self; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_PIN, + reinterpret_cast(&self), // any address in this DLL + &self); +} +QT_END_NAMESPACE +#endif + #endif // QT_NO_DBUS -- cgit v1.2.3 From cb320925b9b4c33ffbdac73597bf78db842109c9 Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Fri, 18 Mar 2016 11:56:43 -0400 Subject: Change some QNX defaults Make REDUCE_EXPORTS the default for QNX. This is what the Linux builds use. The Windows builds should too. Turn on ICU detection for QNX. QNX has ICU. Task-number: QTBUG-52578 Change-Id: Ie65c6ff03c4eecf361727b3b6026338f686d9749 Reviewed-by: Dan Cape Reviewed-by: Oswald Buddenhagen --- tools/configure/configureapp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 6f1e2b7d2d..3be0ea2b7c 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1742,6 +1742,7 @@ void Configure::applySpecSpecifics() dictionary["DECORATIONS"] = "default windows styled"; } else if ((platform() == QNX) || (platform() == BLACKBERRY)) { + dictionary[ "REDUCE_EXPORTS" ] = "yes"; dictionary["STACK_PROTECTOR_STRONG"] = "auto"; dictionary["SLOG2"] = "auto"; dictionary["QNX_IMF"] = "auto"; @@ -1751,6 +1752,7 @@ void Configure::applySpecSpecifics() dictionary[ "ANGLE" ] = "no"; dictionary[ "DYNAMICGL" ] = "no"; dictionary[ "FONT_CONFIG" ] = "auto"; + dictionary[ "ICU" ] = "auto"; } else if (platform() == ANDROID) { dictionary[ "REDUCE_EXPORTS" ] = "yes"; dictionary[ "BUILD" ] = "release"; -- cgit v1.2.3 From 6efa3215a2724415ec7c11e3631594ada1b722b0 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 15 Apr 2016 16:51:04 +0200 Subject: QOpenGLCustomShaderStage - fix a memory leak Coverity found a memory leak - CID-10995. Fix a dtor + make copy constructor / assignment operator private (Q_DISABLE_COPY). Change-Id: I4f046d075b60fbfb69f350e4a4d8b07ea1643914 Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglcustomshaderstage.cpp | 1 + src/gui/opengl/qopenglcustomshaderstage_p.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/gui/opengl/qopenglcustomshaderstage.cpp b/src/gui/opengl/qopenglcustomshaderstage.cpp index e0d131e64d..e5504e6195 100644 --- a/src/gui/opengl/qopenglcustomshaderstage.cpp +++ b/src/gui/opengl/qopenglcustomshaderstage.cpp @@ -63,6 +63,7 @@ QOpenGLCustomShaderStage::~QOpenGLCustomShaderStage() d->m_manager->removeCustomStage(); d->m_manager->sharedShaders->cleanupCustomStage(this); } + delete d_ptr; } void QOpenGLCustomShaderStage::setUniformsDirty() diff --git a/src/gui/opengl/qopenglcustomshaderstage_p.h b/src/gui/opengl/qopenglcustomshaderstage_p.h index 78c414d316..9b3c9fbce1 100644 --- a/src/gui/opengl/qopenglcustomshaderstage_p.h +++ b/src/gui/opengl/qopenglcustomshaderstage_p.h @@ -46,6 +46,7 @@ // #include +#include QT_BEGIN_NAMESPACE @@ -72,6 +73,8 @@ protected: private: QOpenGLCustomShaderStagePrivate* d_ptr; + + Q_DISABLE_COPY(QOpenGLCustomShaderStage) }; -- cgit v1.2.3 From e34ebe632825433d591165db737f732f741bbd9f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 21 Apr 2016 20:02:20 +0200 Subject: automate the installation of some more example source files Change-Id: I61f9f4882c5a7743817059824250958f5ce4a603 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_example_installs.prf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mkspecs/features/qt_example_installs.prf b/mkspecs/features/qt_example_installs.prf index a644904981..ebf68a8a21 100644 --- a/mkspecs/features/qt_example_installs.prf +++ b/mkspecs/features/qt_example_installs.prf @@ -47,8 +47,13 @@ probase = $$relative_path($$_PRO_FILE_PWD_, $$dirname(_QMAKE_CONF_)/examples) sourcefiles += $$resrc } } + sourcefiles += \ + $$ANDROID_PACKAGE_SOURCE_DIR \ + $$QMAKE_INFO_PLIST \ + $$DISTFILES extras = \ $$_PRO_FILE_PWD_/README \ + $$_PRO_FILE_PWD_/README.TXT \ $$files($$_PRO_FILE_PWD_/*.pri) \ $$replace(_PRO_FILE_, \\.pro$, .qmlproject) \ $$replace(_PRO_FILE_, \\.pro$, .json) \ -- cgit v1.2.3 From 5bbbea4c83149d6920cff2991fc2458c49a1004e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 26 Apr 2016 14:43:01 +0200 Subject: normalize structure of plugandpaint example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit as in other examples which come with plugins, use an additional hierarchy level which contains the app and plugin subdirs. Change-Id: I2487755967aa3474c337c8c8af10be49627b63d0 Reviewed-by: Topi Reiniö --- .gitignore | 1 - examples/widgets/doc/src/plugandpaint.qdoc | 120 ++++---- examples/widgets/tools/plugandpaint/app/app.pro | 26 ++ .../widgets/tools/plugandpaint/app/interfaces.h | 114 ++++++++ examples/widgets/tools/plugandpaint/app/main.cpp | 55 ++++ .../widgets/tools/plugandpaint/app/mainwindow.cpp | 309 +++++++++++++++++++++ .../widgets/tools/plugandpaint/app/mainwindow.h | 103 +++++++ .../widgets/tools/plugandpaint/app/paintarea.cpp | 195 +++++++++++++ .../widgets/tools/plugandpaint/app/paintarea.h | 91 ++++++ .../tools/plugandpaint/app/plugindialog.cpp | 156 +++++++++++ .../widgets/tools/plugandpaint/app/plugindialog.h | 76 +++++ examples/widgets/tools/plugandpaint/interfaces.h | 114 -------- examples/widgets/tools/plugandpaint/main.cpp | 55 ---- examples/widgets/tools/plugandpaint/mainwindow.cpp | 309 --------------------- examples/widgets/tools/plugandpaint/mainwindow.h | 103 ------- examples/widgets/tools/plugandpaint/paintarea.cpp | 195 ------------- examples/widgets/tools/plugandpaint/paintarea.h | 91 ------ .../widgets/tools/plugandpaint/plugandpaint.pro | 25 +- .../widgets/tools/plugandpaint/plugindialog.cpp | 156 ----------- examples/widgets/tools/plugandpaint/plugindialog.h | 76 ----- .../plugins/basictools/basictools.json | 1 + .../plugandpaint/plugins/basictools/basictools.pro | 14 + .../plugins/basictools/basictoolsplugin.cpp | 191 +++++++++++++ .../plugins/basictools/basictoolsplugin.h | 91 ++++++ .../plugins/extrafilters/extrafilters.json | 1 + .../plugins/extrafilters/extrafilters.pro | 14 + .../plugins/extrafilters/extrafiltersplugin.cpp | 122 ++++++++ .../plugins/extrafilters/extrafiltersplugin.h | 65 +++++ .../widgets/tools/plugandpaint/plugins/plugins.pro | 3 + .../plugandpaintplugins/basictools/basictools.json | 1 - .../plugandpaintplugins/basictools/basictools.pro | 14 - .../basictools/basictoolsplugin.cpp | 191 ------------- .../basictools/basictoolsplugin.h | 91 ------ .../extrafilters/extrafilters.json | 1 - .../extrafilters/extrafilters.pro | 14 - .../extrafilters/extrafiltersplugin.cpp | 122 -------- .../extrafilters/extrafiltersplugin.h | 65 ----- .../plugandpaintplugins/plugandpaintplugins.pro | 3 - examples/widgets/tools/tools.pro | 3 - src/corelib/kernel/qobject.cpp | 8 +- src/corelib/plugin/qplugin.qdoc | 6 +- 41 files changed, 1696 insertions(+), 1695 deletions(-) create mode 100644 examples/widgets/tools/plugandpaint/app/app.pro create mode 100644 examples/widgets/tools/plugandpaint/app/interfaces.h create mode 100644 examples/widgets/tools/plugandpaint/app/main.cpp create mode 100644 examples/widgets/tools/plugandpaint/app/mainwindow.cpp create mode 100644 examples/widgets/tools/plugandpaint/app/mainwindow.h create mode 100644 examples/widgets/tools/plugandpaint/app/paintarea.cpp create mode 100644 examples/widgets/tools/plugandpaint/app/paintarea.h create mode 100644 examples/widgets/tools/plugandpaint/app/plugindialog.cpp create mode 100644 examples/widgets/tools/plugandpaint/app/plugindialog.h delete mode 100644 examples/widgets/tools/plugandpaint/interfaces.h delete mode 100644 examples/widgets/tools/plugandpaint/main.cpp delete mode 100644 examples/widgets/tools/plugandpaint/mainwindow.cpp delete mode 100644 examples/widgets/tools/plugandpaint/mainwindow.h delete mode 100644 examples/widgets/tools/plugandpaint/paintarea.cpp delete mode 100644 examples/widgets/tools/plugandpaint/paintarea.h delete mode 100644 examples/widgets/tools/plugandpaint/plugindialog.cpp delete mode 100644 examples/widgets/tools/plugandpaint/plugindialog.h create mode 100644 examples/widgets/tools/plugandpaint/plugins/basictools/basictools.json create mode 100644 examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro create mode 100644 examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp create mode 100644 examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h create mode 100644 examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.json create mode 100644 examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro create mode 100644 examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.cpp create mode 100644 examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.h create mode 100644 examples/widgets/tools/plugandpaint/plugins/plugins.pro delete mode 100644 examples/widgets/tools/plugandpaintplugins/basictools/basictools.json delete mode 100644 examples/widgets/tools/plugandpaintplugins/basictools/basictools.pro delete mode 100644 examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp delete mode 100644 examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h delete mode 100644 examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.json delete mode 100644 examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.pro delete mode 100644 examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.cpp delete mode 100644 examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.h delete mode 100644 examples/widgets/tools/plugandpaintplugins/plugandpaintplugins.pro diff --git a/.gitignore b/.gitignore index 1ecd8c1009..7179340e20 100644 --- a/.gitignore +++ b/.gitignore @@ -226,7 +226,6 @@ config.tests/unix/sse2/sse2 # --------------------- debug -examples/tools/plugandpaint/plugins include/* include/*/* lib/* diff --git a/examples/widgets/doc/src/plugandpaint.qdoc b/examples/widgets/doc/src/plugandpaint.qdoc index b139de9fa1..a79f8546ea 100644 --- a/examples/widgets/doc/src/plugandpaint.qdoc +++ b/examples/widgets/doc/src/plugandpaint.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \example tools/plugandpaint + \example tools/plugandpaint/app \title Plug & Paint Example \ingroup examples-widgets-tools @@ -47,8 +47,8 @@ through plugins, we recommend that you start by reading this overview, which explains how to make an application use plugins. Afterwards, you can read the - \l{tools/plugandpaintplugins/basictools}{Basic Tools} and - \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} + \l{tools/plugandpaint/plugins/basictools}{Basic Tools} and + \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} overviews, which show how to implement static and dynamic plugins, respectively. @@ -74,7 +74,7 @@ in the plugins. - \snippet tools/plugandpaint/interfaces.h 0 + \snippet tools/plugandpaint/app/interfaces.h 0 The \c BrushInterface class declares four pure virtual functions. The first pure virtual function, \c brushes(), returns a list of @@ -96,7 +96,7 @@ virtual destructor. We provide the destructor to keep these compilers happy. - \snippet tools/plugandpaint/interfaces.h 1 + \snippet tools/plugandpaint/app/interfaces.h 1 The \c ShapeInterface class declares a \c shapes() function that works the same as \c{BrushInterface}'s \c brushes() function, and @@ -106,13 +106,13 @@ parent parameter can be used by the plugin to pop up a dialog asking the user to specify more information. - \snippet tools/plugandpaint/interfaces.h 2 + \snippet tools/plugandpaint/app/interfaces.h 2 The \c FilterInterface class declares a \c filters() function that returns a list of filter names, and a \c filterImage() function that applies a filter to an image. - \snippet tools/plugandpaint/interfaces.h 4 + \snippet tools/plugandpaint/app/interfaces.h 4 To make it possible to query at run-time whether a plugin implements a given interface, we must use the \c @@ -125,8 +125,8 @@ a good idea to include a version number in the string, as we did above. - The \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin - and the \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} + The \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin + and the \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} plugin shows how to derive from \c BrushInterface, \c ShapeInterface, and \c FilterInterface. @@ -144,7 +144,7 @@ \l{mainwindows/application}{Application}). Here, we'll concentrate on the parts of the code that are related to plugins. - \snippet tools/plugandpaint/mainwindow.cpp 4 + \snippet tools/plugandpaint/app/mainwindow.cpp 4 The \c loadPlugins() function is called from the \c MainWindow constructor to detect plugins and update the \uicontrol{Brush}, @@ -155,7 +155,7 @@ QObject. That QObject implements plugin interfaces using multiple inheritance. - \snippet tools/plugandpaint/mainwindow.cpp 5 + \snippet tools/plugandpaint/app/mainwindow.cpp 5 The next step is to load dynamic plugins. We initialize the \c pluginsDir member variable to refer to the \c plugins @@ -166,9 +166,9 @@ this file is usually located in a subdirectory, so we need to take this into account. - \snippet tools/plugandpaint/mainwindow.cpp 6 - \snippet tools/plugandpaint/mainwindow.cpp 7 - \snippet tools/plugandpaint/mainwindow.cpp 8 + \snippet tools/plugandpaint/app/mainwindow.cpp 6 + \snippet tools/plugandpaint/app/mainwindow.cpp 7 + \snippet tools/plugandpaint/app/mainwindow.cpp 8 We use QDir::entryList() to get a list of all files in that directory. Then we iterate over the result using \l foreach and @@ -181,12 +181,12 @@ If QPluginLoader::instance() is non-null, we add it to the menus. - \snippet tools/plugandpaint/mainwindow.cpp 9 + \snippet tools/plugandpaint/app/mainwindow.cpp 9 At the end, we enable or disable the \uicontrol{Brush}, \uicontrol{Shapes}, and \uicontrol{Filters} menus based on whether they contain any items. - \snippet tools/plugandpaint/mainwindow.cpp 10 + \snippet tools/plugandpaint/app/mainwindow.cpp 10 For each plugin (static or dynamic), we check which interfaces it implements using \l qobject_cast(). First, we try to cast the @@ -195,7 +195,7 @@ by \c brushes(). Then we do the same with the \c ShapeInterface and the \c FilterInterface. - \snippet tools/plugandpaint/mainwindow.cpp 3 + \snippet tools/plugandpaint/app/mainwindow.cpp 3 The \c aboutPlugins() slot is called on startup and can be invoked at any time through the \uicontrol{About Plugins} action. It @@ -211,7 +211,7 @@ plugin from which it comes from as the parent; this makes it convenient to get access to the plugin later. - \snippet tools/plugandpaint/mainwindow.cpp 0 + \snippet tools/plugandpaint/app/mainwindow.cpp 0 The \c changeBrush() slot is invoked when the user chooses one of the brushes from the \uicontrol{Brush} menu. We start by finding out @@ -222,7 +222,7 @@ identifying the brush. Next time the user draws on the paint area, \c PaintArea will use this brush. - \snippet tools/plugandpaint/mainwindow.cpp 1 + \snippet tools/plugandpaint/app/mainwindow.cpp 1 The \c insertShape() is invoked when the use chooses one of the shapes from the \uicontrol{Shapes} menu. We retrieve the QAction that @@ -230,7 +230,7 @@ QAction, and finally we call \c ShapeInterface::generateShape() to obtain a QPainterPath. - \snippet tools/plugandpaint/mainwindow.cpp 2 + \snippet tools/plugandpaint/app/mainwindow.cpp 2 The \c applyFilter() slot is similar: We retrieve the QAction that invoked the slot, then the \c FilterInterface associated to @@ -243,12 +243,12 @@ The \c PaintArea class contains some code that deals with \c BrushInterface, so we'll review it briefly. - \snippet tools/plugandpaint/paintarea.cpp 0 + \snippet tools/plugandpaint/app/paintarea.cpp 0 In \c setBrush(), we simply store the \c BrushInterface and the brush that are given to us by \c MainWindow. - \snippet tools/plugandpaint/paintarea.cpp 1 + \snippet tools/plugandpaint/app/paintarea.cpp 1 In the \l{QWidget::mouseMoveEvent()}{mouse move event handler}, we call the \c BrushInterface::mouseMove() function on the @@ -262,7 +262,7 @@ and a list of plugin file names. It calls \c findPlugins() to fill the QTreeWdiget with information about the plugins: - \snippet tools/plugandpaint/plugindialog.cpp 0 + \snippet tools/plugandpaint/app/plugindialog.cpp 0 The \c findPlugins() is very similar to \c MainWindow::loadPlugins(). It uses QPluginLoader to access the @@ -270,11 +270,11 @@ populateTreeWidget() uses \l qobject_cast() to find out which interfaces are implemented by the plugins: - \snippet tools/plugandpaint/plugindialog.cpp 1 + \snippet tools/plugandpaint/app/plugindialog.cpp 1 \section1 Importing Static Plugins - The \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin + The \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin is built as a static plugin, to ensure that it is always available to the application. This requires using the Q_IMPORT_PLUGIN() macro somewhere in the application (in a \c @@ -283,7 +283,7 @@ For Plug & Paint, we have chosen to put Q_IMPORT_PLUGIN() in \c main.cpp: - \snippet tools/plugandpaint/main.cpp 0 + \snippet tools/plugandpaint/app/main.cpp 0 The argument to Q_IMPORT_PLUGIN() is the plugin name, which corresponds with the name of the class that declares metadata for the plugin with @@ -292,10 +292,10 @@ In the \c .pro file, we need to specify the static library. Here's the project file for building Plug & Paint: - \snippet tools/plugandpaint/plugandpaint.pro 0 + \snippet tools/plugandpaint/app/app.pro 0 The \c LIBS line variable specifies the library \c pnp_basictools - located in the \c ../plugandpaintplugins/basictools directory. + located in the \c ../plugandpaint/plugins/basictools directory. (Although the \c LIBS syntax has a distinct Unix flavor, \c qmake supports it on all platforms.) @@ -306,19 +306,19 @@ This completes our review of the Plug & Paint application. At this point, you might want to take a look at the - \l{tools/plugandpaintplugins/basictools}{Basic Tools} example + \l{tools/plugandpaint/plugins/basictools}{Basic Tools} example plugin. */ /*! - \example tools/plugandpaintplugins/basictools + \example tools/plugandpaint/plugins/basictools \title Plug & Paint Basic Tools Example \brief A plugin providing the basic tools for painting functionality. \image plugandpaint.png Screenshot of the Plug & Paint example The Basic Tools example is a static plugin for the - \l{tools/plugandpaint}{Plug & Paint} example. It provides a set + \l{tools/plugandpaint/app}{Plug & Paint} example. It provides a set of basic brushes, shapes, and filters. Through the Basic Tools example, we will review the four steps involved in writing a Qt plugin: @@ -332,13 +332,13 @@ \section1 Declaration of the Plugin Class - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.h 0 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 0 We start by including \c interfaces.h, which defines the plugin - interfaces for the \l{tools/plugandpaint}{Plug & Paint} + interfaces for the \l{tools/plugandpaint/app}{Plug & Paint} application. For the \c #include to work, we need to add an \c - INCLUDEPATH entry to the \c .pro file with the path to Qt's \c - examples/tools directory. + INCLUDEPATH entry to the \c .pro file with the path to the + header file. The \c BasicToolsPlugin class is a QObject subclass that implements the \c BrushInterface, the \c ShapeInterface, and the @@ -346,12 +346,12 @@ The \c Q_INTERFACES() macro is necessary to tell \l{moc}, Qt's meta-object compiler, that the base classes are plugin interfaces. Without the \c Q_INTERFACES() macro, we couldn't use - \l qobject_cast() in the \l{tools/plugandpaint}{Plug & Paint} + \l qobject_cast() in the \l{tools/plugandpaint/app}{Plug & Paint} application to detect interfaces. For an explanation for the \c Q_PLUGIN_METADATA() macro see \l {Exporting the Plugin}. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.h 2 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 2 In the \c public section of the class, we declare all the functions from the three interfaces. @@ -361,23 +361,23 @@ Let's now review the implementation of the \c BasicToolsPlugin member functions inherited from \c BrushInterface. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 0 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 0 The \c brushes() function returns a list of brushes provided by this plugin. We provide three brushes: \uicontrol{Pencil}, \uicontrol{Air Brush}, and \uicontrol{Random Letters}. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 1 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 1 On a mouse press event, we just call \c mouseMove() to draw the spot where the event occurred. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 2 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 2 In \c mouseMove(), we start by saving the state of the QPainter and we compute a few variables that we'll need later. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 3 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 3 Then comes the brush-dependent part of the code: @@ -399,14 +399,14 @@ At the end, we restore the painter state to what it was upon entering the function and we return the bounding rectangle. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 4 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 4 When the user releases the mouse, we do nothing and return an empty QRect. \section1 Implementation of the Shape Interface - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 5 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 5 The plugin provides three shapes: \uicontrol{Circle}, \uicontrol{Star}, and \uicontrol{Text...}. The three dots after \uicontrol{Text} are there because @@ -418,7 +418,7 @@ distinguish between the internal shape name and the name used in the user interface. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 6 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 6 The \c generateShape() creates a QPainterPath for the specified shape. If the shape is \uicontrol{Text}, we pop up a QInputDialog to @@ -426,12 +426,12 @@ \section1 Implementation of the Filter Interface - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 7 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 7 The plugin provides three filters: \uicontrol{Invert Pixels}, \uicontrol{Swap RGB}, and \uicontrol{Grayscale}. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.cpp 8 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp 8 The \c filterImage() function takes a filter name and a QImage as parameters and returns an altered QImage. The first thing we do @@ -450,7 +450,7 @@ It must contain the plugins IID and optionally a filename pointing to a json file containing the metadata for the plugin. - \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.h 4 + \snippet tools/plugandpaint/plugins/basictools/basictoolsplugin.h 4 Within this example the json file does not need to export any metadata, so it just contains an empty json object. @@ -463,7 +463,7 @@ Here's the project file for building the Basic Tools plugin: - \snippet tools/plugandpaintplugins/basictools/basictools.pro 0 + \snippet tools/plugandpaint/plugins/basictools/basictools.pro 0 The \c .pro file differs from typical \c .pro files in many respects. First, it starts with a \c TEMPLATE entry specifying \c @@ -475,15 +475,14 @@ To make the plugin a static plugin, all that is required is to specify \c static in addition to \c plugin. The - \l{tools/plugandpaintplugins/extrafilters}{Extra Filters} plugin, + \l{tools/plugandpaint/plugins/extrafilters}{Extra Filters} plugin, which is compiled as a dynamic plugin, doesn't specify \c static in its \c .pro file. The \c INCLUDEPATH variable sets the search paths for global headers (i.e., header files included using \c{#include <...>}). - We add Qt's \c examples/tools directory (strictly speaking, - \c{examples/tools/plugandpaintplugins/basictools/../..}) to the - list, so that we can include \c . + We add \c ../../app to the list, so that we can include + \c . The \c TARGET variable specifies which name we want to give the target library. We use \c pnp_ as the prefix to show that the @@ -499,27 +498,27 @@ */ /*! - \example tools/plugandpaintplugins/extrafilters + \example tools/plugandpaint/plugins/extrafilters \title Plug & Paint Extra Filters Example \brief A plugin providing the extra filters. \image plugandpaint.png Screenshot of the Plug & Paint example The Extra Filters example is a plugin for the - \l{tools/plugandpaint}{Plug & Paint} example. It provides a set + \l{tools/plugandpaint/app}{Plug & Paint} example. It provides a set of filters in addition to those provided by the - \l{tools/plugandpaintplugins/basictools}{Basic Tools} plugin. + \l{tools/plugandpaint/plugins/basictools}{Basic Tools} plugin. Since the approach is identical to - \l{tools/plugandpaintplugins/basictools}{Basic Tools}, we won't + \l{tools/plugandpaint/plugins/basictools}{Basic Tools}, we won't review the code here. The only part of interest is the \c .pro file, since Extra Filters is a dynamic plugin - (\l{tools/plugandpaintplugins/basictools}{Basic Tools} is + (\l{tools/plugandpaint/plugins/basictools}{Basic Tools} is linked statically into the Plug & Paint executable). Here's the project file for building the Extra Filters plugin: - \snippet tools/plugandpaintplugins/extrafilters/extrafilters.pro 0 + \snippet tools/plugandpaint/plugins/extrafilters/extrafilters.pro 0 The \c .pro file differs from typical \c .pro files in many respects. First, it starts with a \c TEMPLATE entry specifying \c @@ -531,9 +530,8 @@ The \c INCLUDEPATH variable sets the search paths for global headers (i.e., header files included using \c{#include <...>}). - We add Qt's \c examples/tools directory (strictly speaking, - \c{examples/tools/plugandpaintplugins/basictools/../..}) to the - list, so that we can include \c . + We add \c ../../app to the list, so that we can include + \c . The \c TARGET variable specifies which name we want to give the target library. We use \c pnp_ as the prefix to show that the diff --git a/examples/widgets/tools/plugandpaint/app/app.pro b/examples/widgets/tools/plugandpaint/app/app.pro new file mode 100644 index 0000000000..45fb7224e0 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/app.pro @@ -0,0 +1,26 @@ +#! [0] +TARGET = plugandpaint +DESTDIR = .. + +QT += widgets + +HEADERS = interfaces.h \ + mainwindow.h \ + paintarea.h \ + plugindialog.h +SOURCES = main.cpp \ + mainwindow.cpp \ + paintarea.cpp \ + plugindialog.cpp + +LIBS = -L../plugins -lpnp_basictools + +if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { + mac:LIBS = $$member(LIBS, 0) $$member(LIBS, 1)_debug + win32:LIBS = $$member(LIBS, 0) $$member(LIBS, 1)d +} +#! [0] + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint +INSTALLS += target diff --git a/examples/widgets/tools/plugandpaint/app/interfaces.h b/examples/widgets/tools/plugandpaint/app/interfaces.h new file mode 100644 index 0000000000..bf3e2cad02 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/interfaces.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INTERFACES_H +#define INTERFACES_H + +#include + +QT_BEGIN_NAMESPACE +class QImage; +class QPainter; +class QWidget; +class QPainterPath; +class QPoint; +class QRect; +class QString; +class QStringList; +QT_END_NAMESPACE + +//! [0] +class BrushInterface +{ +public: + virtual ~BrushInterface() {} + + virtual QStringList brushes() const = 0; + virtual QRect mousePress(const QString &brush, QPainter &painter, + const QPoint &pos) = 0; + virtual QRect mouseMove(const QString &brush, QPainter &painter, + const QPoint &oldPos, const QPoint &newPos) = 0; + virtual QRect mouseRelease(const QString &brush, QPainter &painter, + const QPoint &pos) = 0; +}; +//! [0] + +//! [1] +class ShapeInterface +{ +public: + virtual ~ShapeInterface() {} + + virtual QStringList shapes() const = 0; + virtual QPainterPath generateShape(const QString &shape, + QWidget *parent) = 0; +}; +//! [1] + +//! [2] +class FilterInterface +{ +public: + virtual ~FilterInterface() {} + + virtual QStringList filters() const = 0; + virtual QImage filterImage(const QString &filter, const QImage &image, + QWidget *parent) = 0; +}; +//! [2] + +QT_BEGIN_NAMESPACE +//! [3] //! [4] +#define BrushInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" + +Q_DECLARE_INTERFACE(BrushInterface, BrushInterface_iid) +//! [3] + +#define ShapeInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.ShapeInterface" + +Q_DECLARE_INTERFACE(ShapeInterface, ShapeInterface_iid) +//! [5] +#define FilterInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" + +Q_DECLARE_INTERFACE(FilterInterface, FilterInterface_iid) +//! [4] //! [5] +QT_END_NAMESPACE + +#endif diff --git a/examples/widgets/tools/plugandpaint/app/main.cpp b/examples/widgets/tools/plugandpaint/app/main.cpp new file mode 100644 index 0000000000..d4b7d72927 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#include "mainwindow.h" +#include +#include + +Q_IMPORT_PLUGIN(BasicToolsPlugin) + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWindow window; + window.show(); + return app.exec(); +} +//! [0] diff --git a/examples/widgets/tools/plugandpaint/app/mainwindow.cpp b/examples/widgets/tools/plugandpaint/app/mainwindow.cpp new file mode 100644 index 0000000000..4cb9ac8e4d --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/mainwindow.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "interfaces.h" +#include "mainwindow.h" +#include "paintarea.h" +#include "plugindialog.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow() : + paintArea(new PaintArea), + scrollArea(new QScrollArea) +{ + scrollArea->setBackgroundRole(QPalette::Dark); + scrollArea->setWidget(paintArea); + setCentralWidget(scrollArea); + + createActions(); + createMenus(); + loadPlugins(); + + setWindowTitle(tr("Plug & Paint")); + + if (!brushActionGroup->actions().isEmpty()) + brushActionGroup->actions().first()->trigger(); + + QTimer::singleShot(500, this, SLOT(aboutPlugins())); +} + +void MainWindow::open() +{ + const QString fileName = QFileDialog::getOpenFileName(this, + tr("Open File"), + QDir::currentPath()); + if (!fileName.isEmpty()) { + if (!paintArea->openImage(fileName)) { + QMessageBox::information(this, tr("Plug & Paint"), + tr("Cannot load %1.").arg(fileName)); + return; + } + paintArea->adjustSize(); + } +} + +bool MainWindow::saveAs() +{ + const QString initialPath = QDir::currentPath() + "/untitled.png"; + + const QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), + initialPath); + if (fileName.isEmpty()) { + return false; + } else { + return paintArea->saveImage(fileName, "png"); + } +} + +void MainWindow::brushColor() +{ + const QColor newColor = QColorDialog::getColor(paintArea->brushColor()); + if (newColor.isValid()) + paintArea->setBrushColor(newColor); +} + +void MainWindow::brushWidth() +{ + bool ok; + const int newWidth = QInputDialog::getInt(this, tr("Plug & Paint"), + tr("Select brush width:"), + paintArea->brushWidth(), + 1, 50, 1, &ok); + if (ok) + paintArea->setBrushWidth(newWidth); +} + +//! [0] +void MainWindow::changeBrush() +{ + QAction *action = qobject_cast(sender()); + BrushInterface *iBrush = qobject_cast(action->parent()); + const QString brush = action->text(); + + paintArea->setBrush(iBrush, brush); +} +//! [0] + +//! [1] +void MainWindow::insertShape() +{ + QAction *action = qobject_cast(sender()); + ShapeInterface *iShape = qobject_cast(action->parent()); + + const QPainterPath path = iShape->generateShape(action->text(), this); + if (!path.isEmpty()) + paintArea->insertShape(path); +} +//! [1] + +//! [2] +void MainWindow::applyFilter() +{ + QAction *action = qobject_cast(sender()); + FilterInterface *iFilter = + qobject_cast(action->parent()); + + const QImage image = iFilter->filterImage(action->text(), paintArea->image(), + this); + paintArea->setImage(image); +} +//! [2] + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Plug & Paint"), + tr("The Plug & Paint example demonstrates how to write Qt " + "applications that can be extended through plugins.")); +} + +//! [3] +void MainWindow::aboutPlugins() +{ + PluginDialog dialog(pluginsDir.path(), pluginFileNames, this); + dialog.exec(); +} +//! [3] + +void MainWindow::createActions() +{ + openAct = new QAction(tr("&Open..."), this); + openAct->setShortcuts(QKeySequence::Open); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); + + saveAsAct = new QAction(tr("&Save As..."), this); + saveAsAct->setShortcuts(QKeySequence::SaveAs); + connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); + + exitAct = new QAction(tr("E&xit"), this); + exitAct->setShortcuts(QKeySequence::Quit); + connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); + + brushColorAct = new QAction(tr("&Brush Color..."), this); + connect(brushColorAct, SIGNAL(triggered()), this, SLOT(brushColor())); + + brushWidthAct = new QAction(tr("&Brush Width..."), this); + connect(brushWidthAct, SIGNAL(triggered()), this, SLOT(brushWidth())); + + brushActionGroup = new QActionGroup(this); + + aboutAct = new QAction(tr("&About"), this); + connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + + aboutQtAct = new QAction(tr("About &Qt"), this); + connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + + aboutPluginsAct = new QAction(tr("About &Plugins"), this); + connect(aboutPluginsAct, SIGNAL(triggered()), this, SLOT(aboutPlugins())); +} + +void MainWindow::createMenus() +{ + fileMenu = menuBar()->addMenu(tr("&File")); + fileMenu->addAction(openAct); + fileMenu->addAction(saveAsAct); + fileMenu->addSeparator(); + fileMenu->addAction(exitAct); + + brushMenu = menuBar()->addMenu(tr("&Brush")); + brushMenu->addAction(brushColorAct); + brushMenu->addAction(brushWidthAct); + brushMenu->addSeparator(); + + shapesMenu = menuBar()->addMenu(tr("&Shapes")); + + filterMenu = menuBar()->addMenu(tr("&Filter")); + + menuBar()->addSeparator(); + + helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(aboutAct); + helpMenu->addAction(aboutQtAct); + helpMenu->addAction(aboutPluginsAct); +} + +//! [4] +void MainWindow::loadPlugins() +{ + foreach (QObject *plugin, QPluginLoader::staticInstances()) + populateMenus(plugin); +//! [4] //! [5] + + pluginsDir = QDir(qApp->applicationDirPath()); + +#if defined(Q_OS_WIN) + if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") + pluginsDir.cdUp(); +#elif defined(Q_OS_MAC) + if (pluginsDir.dirName() == "MacOS") { + pluginsDir.cdUp(); + pluginsDir.cdUp(); + pluginsDir.cdUp(); + } +#endif + pluginsDir.cd("plugins"); +//! [5] + +//! [6] + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (plugin) { + populateMenus(plugin); + pluginFileNames += fileName; +//! [6] //! [7] + } +//! [7] //! [8] + } +//! [8] + +//! [9] + brushMenu->setEnabled(!brushActionGroup->actions().isEmpty()); + shapesMenu->setEnabled(!shapesMenu->actions().isEmpty()); + filterMenu->setEnabled(!filterMenu->actions().isEmpty()); +} +//! [9] + +//! [10] +void MainWindow::populateMenus(QObject *plugin) +{ + BrushInterface *iBrush = qobject_cast(plugin); + if (iBrush) + addToMenu(plugin, iBrush->brushes(), brushMenu, SLOT(changeBrush()), + brushActionGroup); + + ShapeInterface *iShape = qobject_cast(plugin); + if (iShape) + addToMenu(plugin, iShape->shapes(), shapesMenu, SLOT(insertShape())); + + FilterInterface *iFilter = qobject_cast(plugin); + if (iFilter) + addToMenu(plugin, iFilter->filters(), filterMenu, SLOT(applyFilter())); +} +//! [10] + +void MainWindow::addToMenu(QObject *plugin, const QStringList &texts, + QMenu *menu, const char *member, + QActionGroup *actionGroup) +{ + foreach (QString text, texts) { + QAction *action = new QAction(text, plugin); + connect(action, SIGNAL(triggered()), this, member); + menu->addAction(action); + + if (actionGroup) { + action->setCheckable(true); + actionGroup->addAction(action); + } + } +} diff --git a/examples/widgets/tools/plugandpaint/app/mainwindow.h b/examples/widgets/tools/plugandpaint/app/mainwindow.h new file mode 100644 index 0000000000..06f7157d80 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/mainwindow.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QActionGroup; +class QMenu; +class QScrollArea; +QT_END_NAMESPACE +class PaintArea; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + +private slots: + void open(); + bool saveAs(); + void brushColor(); + void brushWidth(); + void changeBrush(); + void insertShape(); + void applyFilter(); + void about(); + void aboutPlugins(); + +private: + void createActions(); + void createMenus(); + void loadPlugins(); + void populateMenus(QObject *plugin); + void addToMenu(QObject *plugin, const QStringList &texts, QMenu *menu, + const char *member, QActionGroup *actionGroup = 0); + + PaintArea *paintArea; + QScrollArea *scrollArea; + QDir pluginsDir; + QStringList pluginFileNames; + + QMenu *fileMenu; + QMenu *brushMenu; + QMenu *shapesMenu; + QMenu *filterMenu; + QMenu *helpMenu; + QActionGroup *brushActionGroup; + QAction *openAct; + QAction *saveAsAct; + QAction *exitAct; + QAction *brushWidthAct; + QAction *brushColorAct; + QAction *aboutAct; + QAction *aboutQtAct; + QAction *aboutPluginsAct; +}; + +#endif diff --git a/examples/widgets/tools/plugandpaint/app/paintarea.cpp b/examples/widgets/tools/plugandpaint/app/paintarea.cpp new file mode 100644 index 0000000000..f5816c6d8e --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/paintarea.cpp @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "interfaces.h" +#include "paintarea.h" + +#include +#include + +PaintArea::PaintArea(QWidget *parent) : + QWidget(parent), + theImage(500, 400, QImage::Format_RGB32), + color(Qt::blue), + thickness(3), + brushInterface(0), + lastPos(-1, -1) +{ + setAttribute(Qt::WA_StaticContents); + setAttribute(Qt::WA_NoBackground); + + theImage.fill(qRgb(255, 255, 255)); +} + +bool PaintArea::openImage(const QString &fileName) +{ + QImage image; + if (!image.load(fileName)) + return false; + + setImage(image); + return true; +} + +bool PaintArea::saveImage(const QString &fileName, const char *fileFormat) +{ + return theImage.save(fileName, fileFormat); +} + +void PaintArea::setImage(const QImage &image) +{ + theImage = image.convertToFormat(QImage::Format_RGB32); + update(); + updateGeometry(); +} + +void PaintArea::insertShape(const QPainterPath &path) +{ + pendingPath = path; +#ifndef QT_NO_CURSOR + setCursor(Qt::CrossCursor); +#endif +} + +void PaintArea::setBrushColor(const QColor &color) +{ + this->color = color; +} + +void PaintArea::setBrushWidth(int width) +{ + thickness = width; +} + +//! [0] +void PaintArea::setBrush(BrushInterface *brushInterface, const QString &brush) +{ + this->brushInterface = brushInterface; + this->brush = brush; +} +//! [0] + +QSize PaintArea::sizeHint() const +{ + return theImage.size(); +} + +void PaintArea::paintEvent(QPaintEvent * /* event */) +{ + QPainter painter(this); + painter.drawImage(QPoint(0, 0), theImage); +} + +void PaintArea::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (!pendingPath.isEmpty()) { + QPainter painter(&theImage); + setupPainter(painter); + + const QRectF boundingRect = pendingPath.boundingRect(); + QLinearGradient gradient(boundingRect.topRight(), + boundingRect.bottomLeft()); + gradient.setColorAt(0.0, QColor(color.red(), color.green(), + color.blue(), 63)); + gradient.setColorAt(1.0, QColor(color.red(), color.green(), + color.blue(), 191)); + painter.setBrush(gradient); + painter.translate(event->pos() - boundingRect.center()); + painter.drawPath(pendingPath); + + pendingPath = QPainterPath(); +#ifndef QT_NO_CURSOR + unsetCursor(); +#endif + update(); + } else { + if (brushInterface) { + QPainter painter(&theImage); + setupPainter(painter); + const QRect rect = brushInterface->mousePress(brush, painter, + event->pos()); + update(rect); + } + + lastPos = event->pos(); + } + } +} + +//! [1] +void PaintArea::mouseMoveEvent(QMouseEvent *event) +{ + if ((event->buttons() & Qt::LeftButton) && lastPos != QPoint(-1, -1)) { + if (brushInterface) { + QPainter painter(&theImage); + setupPainter(painter); + const QRect rect = brushInterface->mouseMove(brush, painter, lastPos, + event->pos()); + update(rect); + } + + lastPos = event->pos(); + } +} +//! [1] + +void PaintArea::mouseReleaseEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && lastPos != QPoint(-1, -1)) { + if (brushInterface) { + QPainter painter(&theImage); + setupPainter(painter); + QRect rect = brushInterface->mouseRelease(brush, painter, + event->pos()); + update(rect); + } + + lastPos = QPoint(-1, -1); + } +} + +void PaintArea::setupPainter(QPainter &painter) +{ + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setPen(QPen(color, thickness, Qt::SolidLine, Qt::RoundCap, + Qt::RoundJoin)); +} diff --git a/examples/widgets/tools/plugandpaint/app/paintarea.h b/examples/widgets/tools/plugandpaint/app/paintarea.h new file mode 100644 index 0000000000..eb953ff5c2 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/paintarea.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PAINTAREA_H +#define PAINTAREA_H + +#include +#include +#include +#include + +class BrushInterface; + +class PaintArea : public QWidget +{ + Q_OBJECT + +public: + PaintArea(QWidget *parent = 0); + + bool openImage(const QString &fileName); + bool saveImage(const QString &fileName, const char *fileFormat); + void setImage(const QImage &image); + void insertShape(const QPainterPath &path); + void setBrushColor(const QColor &color); + void setBrushWidth(int width); + void setBrush(BrushInterface *brushInterface, const QString &brush); + + QImage image() const { return theImage; } + QColor brushColor() const { return color; } + int brushWidth() const { return thickness; } + QSize sizeHint() const Q_DECL_OVERRIDE; + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + +private: + void setupPainter(QPainter &painter); + + QImage theImage; + QColor color; + int thickness; + + BrushInterface *brushInterface; + QString brush; + QPoint lastPos; + + QPainterPath pendingPath; +}; + +#endif diff --git a/examples/widgets/tools/plugandpaint/app/plugindialog.cpp b/examples/widgets/tools/plugandpaint/app/plugindialog.cpp new file mode 100644 index 0000000000..e6ac586c6d --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/plugindialog.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "interfaces.h" +#include "plugindialog.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +PluginDialog::PluginDialog(const QString &path, const QStringList &fileNames, + QWidget *parent) : + QDialog(parent), + label(new QLabel), + treeWidget(new QTreeWidget), + okButton(new QPushButton(tr("OK"))) +{ + treeWidget->setAlternatingRowColors(false); + treeWidget->setSelectionMode(QAbstractItemView::NoSelection); + treeWidget->setColumnCount(1); + treeWidget->header()->hide(); + + okButton->setDefault(true); + + connect(okButton, SIGNAL(clicked()), this, SLOT(close())); + + QGridLayout *mainLayout = new QGridLayout; + mainLayout->setColumnStretch(0, 1); + mainLayout->setColumnStretch(2, 1); + mainLayout->addWidget(label, 0, 0, 1, 3); + mainLayout->addWidget(treeWidget, 1, 0, 1, 3); + mainLayout->addWidget(okButton, 2, 1); + setLayout(mainLayout); + + interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon), + QIcon::Normal, QIcon::On); + interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon), + QIcon::Normal, QIcon::Off); + featureIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon)); + + setWindowTitle(tr("Plugin Information")); + findPlugins(path, fileNames); +} + +//! [0] +void PluginDialog::findPlugins(const QString &path, + const QStringList &fileNames) +{ + label->setText(tr("Plug & Paint found the following plugins\n" + "(looked in %1):") + .arg(QDir::toNativeSeparators(path))); + + const QDir dir(path); + + foreach (QObject *plugin, QPluginLoader::staticInstances()) + populateTreeWidget(plugin, tr("%1 (Static Plugin)") + .arg(plugin->metaObject()->className())); + + foreach (QString fileName, fileNames) { + QPluginLoader loader(dir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (plugin) + populateTreeWidget(plugin, fileName); + } +} +//! [0] + +//! [1] +void PluginDialog::populateTreeWidget(QObject *plugin, const QString &text) +{ + QTreeWidgetItem *pluginItem = new QTreeWidgetItem(treeWidget); + pluginItem->setText(0, text); + treeWidget->setItemExpanded(pluginItem, true); + + QFont boldFont = pluginItem->font(0); + boldFont.setBold(true); + pluginItem->setFont(0, boldFont); + + if (plugin) { + BrushInterface *iBrush = qobject_cast(plugin); + if (iBrush) + addItems(pluginItem, "BrushInterface", iBrush->brushes()); + + ShapeInterface *iShape = qobject_cast(plugin); + if (iShape) + addItems(pluginItem, "ShapeInterface", iShape->shapes()); + + FilterInterface *iFilter = + qobject_cast(plugin); + if (iFilter) + addItems(pluginItem, "FilterInterface", iFilter->filters()); + } +} +//! [1] + +void PluginDialog::addItems(QTreeWidgetItem *pluginItem, + const char *interfaceName, + const QStringList &features) +{ + QTreeWidgetItem *interfaceItem = new QTreeWidgetItem(pluginItem); + interfaceItem->setText(0, interfaceName); + interfaceItem->setIcon(0, interfaceIcon); + + foreach (QString feature, features) { + if (feature.endsWith("...")) + feature.chop(3); + QTreeWidgetItem *featureItem = new QTreeWidgetItem(interfaceItem); + featureItem->setText(0, feature); + featureItem->setIcon(0, featureIcon); + } +} diff --git a/examples/widgets/tools/plugandpaint/app/plugindialog.h b/examples/widgets/tools/plugandpaint/app/plugindialog.h new file mode 100644 index 0000000000..f235d09c31 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/app/plugindialog.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLUGINDIALOG_H +#define PLUGINDIALOG_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QLabel; +class QPushButton; +class QStringList; +class QTreeWidget; +class QTreeWidgetItem; +QT_END_NAMESPACE + +class PluginDialog : public QDialog +{ + Q_OBJECT + +public: + PluginDialog(const QString &path, const QStringList &fileNames, + QWidget *parent = 0); + +private: + void findPlugins(const QString &path, const QStringList &fileNames); + void populateTreeWidget(QObject *plugin, const QString &text); + void addItems(QTreeWidgetItem *pluginItem, const char *interfaceName, + const QStringList &features); + + QLabel *label; + QTreeWidget *treeWidget; + QPushButton *okButton; + QIcon interfaceIcon; + QIcon featureIcon; +}; + +#endif diff --git a/examples/widgets/tools/plugandpaint/interfaces.h b/examples/widgets/tools/plugandpaint/interfaces.h deleted file mode 100644 index bf3e2cad02..0000000000 --- a/examples/widgets/tools/plugandpaint/interfaces.h +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef INTERFACES_H -#define INTERFACES_H - -#include - -QT_BEGIN_NAMESPACE -class QImage; -class QPainter; -class QWidget; -class QPainterPath; -class QPoint; -class QRect; -class QString; -class QStringList; -QT_END_NAMESPACE - -//! [0] -class BrushInterface -{ -public: - virtual ~BrushInterface() {} - - virtual QStringList brushes() const = 0; - virtual QRect mousePress(const QString &brush, QPainter &painter, - const QPoint &pos) = 0; - virtual QRect mouseMove(const QString &brush, QPainter &painter, - const QPoint &oldPos, const QPoint &newPos) = 0; - virtual QRect mouseRelease(const QString &brush, QPainter &painter, - const QPoint &pos) = 0; -}; -//! [0] - -//! [1] -class ShapeInterface -{ -public: - virtual ~ShapeInterface() {} - - virtual QStringList shapes() const = 0; - virtual QPainterPath generateShape(const QString &shape, - QWidget *parent) = 0; -}; -//! [1] - -//! [2] -class FilterInterface -{ -public: - virtual ~FilterInterface() {} - - virtual QStringList filters() const = 0; - virtual QImage filterImage(const QString &filter, const QImage &image, - QWidget *parent) = 0; -}; -//! [2] - -QT_BEGIN_NAMESPACE -//! [3] //! [4] -#define BrushInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" - -Q_DECLARE_INTERFACE(BrushInterface, BrushInterface_iid) -//! [3] - -#define ShapeInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.ShapeInterface" - -Q_DECLARE_INTERFACE(ShapeInterface, ShapeInterface_iid) -//! [5] -#define FilterInterface_iid "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" - -Q_DECLARE_INTERFACE(FilterInterface, FilterInterface_iid) -//! [4] //! [5] -QT_END_NAMESPACE - -#endif diff --git a/examples/widgets/tools/plugandpaint/main.cpp b/examples/widgets/tools/plugandpaint/main.cpp deleted file mode 100644 index d4b7d72927..0000000000 --- a/examples/widgets/tools/plugandpaint/main.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//! [0] -#include "mainwindow.h" -#include -#include - -Q_IMPORT_PLUGIN(BasicToolsPlugin) - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - MainWindow window; - window.show(); - return app.exec(); -} -//! [0] diff --git a/examples/widgets/tools/plugandpaint/mainwindow.cpp b/examples/widgets/tools/plugandpaint/mainwindow.cpp deleted file mode 100644 index 4cb9ac8e4d..0000000000 --- a/examples/widgets/tools/plugandpaint/mainwindow.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "interfaces.h" -#include "mainwindow.h" -#include "paintarea.h" -#include "plugindialog.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MainWindow::MainWindow() : - paintArea(new PaintArea), - scrollArea(new QScrollArea) -{ - scrollArea->setBackgroundRole(QPalette::Dark); - scrollArea->setWidget(paintArea); - setCentralWidget(scrollArea); - - createActions(); - createMenus(); - loadPlugins(); - - setWindowTitle(tr("Plug & Paint")); - - if (!brushActionGroup->actions().isEmpty()) - brushActionGroup->actions().first()->trigger(); - - QTimer::singleShot(500, this, SLOT(aboutPlugins())); -} - -void MainWindow::open() -{ - const QString fileName = QFileDialog::getOpenFileName(this, - tr("Open File"), - QDir::currentPath()); - if (!fileName.isEmpty()) { - if (!paintArea->openImage(fileName)) { - QMessageBox::information(this, tr("Plug & Paint"), - tr("Cannot load %1.").arg(fileName)); - return; - } - paintArea->adjustSize(); - } -} - -bool MainWindow::saveAs() -{ - const QString initialPath = QDir::currentPath() + "/untitled.png"; - - const QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), - initialPath); - if (fileName.isEmpty()) { - return false; - } else { - return paintArea->saveImage(fileName, "png"); - } -} - -void MainWindow::brushColor() -{ - const QColor newColor = QColorDialog::getColor(paintArea->brushColor()); - if (newColor.isValid()) - paintArea->setBrushColor(newColor); -} - -void MainWindow::brushWidth() -{ - bool ok; - const int newWidth = QInputDialog::getInt(this, tr("Plug & Paint"), - tr("Select brush width:"), - paintArea->brushWidth(), - 1, 50, 1, &ok); - if (ok) - paintArea->setBrushWidth(newWidth); -} - -//! [0] -void MainWindow::changeBrush() -{ - QAction *action = qobject_cast(sender()); - BrushInterface *iBrush = qobject_cast(action->parent()); - const QString brush = action->text(); - - paintArea->setBrush(iBrush, brush); -} -//! [0] - -//! [1] -void MainWindow::insertShape() -{ - QAction *action = qobject_cast(sender()); - ShapeInterface *iShape = qobject_cast(action->parent()); - - const QPainterPath path = iShape->generateShape(action->text(), this); - if (!path.isEmpty()) - paintArea->insertShape(path); -} -//! [1] - -//! [2] -void MainWindow::applyFilter() -{ - QAction *action = qobject_cast(sender()); - FilterInterface *iFilter = - qobject_cast(action->parent()); - - const QImage image = iFilter->filterImage(action->text(), paintArea->image(), - this); - paintArea->setImage(image); -} -//! [2] - -void MainWindow::about() -{ - QMessageBox::about(this, tr("About Plug & Paint"), - tr("The Plug & Paint example demonstrates how to write Qt " - "applications that can be extended through plugins.")); -} - -//! [3] -void MainWindow::aboutPlugins() -{ - PluginDialog dialog(pluginsDir.path(), pluginFileNames, this); - dialog.exec(); -} -//! [3] - -void MainWindow::createActions() -{ - openAct = new QAction(tr("&Open..."), this); - openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - - saveAsAct = new QAction(tr("&Save As..."), this); - saveAsAct->setShortcuts(QKeySequence::SaveAs); - connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs())); - - exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - brushColorAct = new QAction(tr("&Brush Color..."), this); - connect(brushColorAct, SIGNAL(triggered()), this, SLOT(brushColor())); - - brushWidthAct = new QAction(tr("&Brush Width..."), this); - connect(brushWidthAct, SIGNAL(triggered()), this, SLOT(brushWidth())); - - brushActionGroup = new QActionGroup(this); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); - - aboutPluginsAct = new QAction(tr("About &Plugins"), this); - connect(aboutPluginsAct, SIGNAL(triggered()), this, SLOT(aboutPlugins())); -} - -void MainWindow::createMenus() -{ - fileMenu = menuBar()->addMenu(tr("&File")); - fileMenu->addAction(openAct); - fileMenu->addAction(saveAsAct); - fileMenu->addSeparator(); - fileMenu->addAction(exitAct); - - brushMenu = menuBar()->addMenu(tr("&Brush")); - brushMenu->addAction(brushColorAct); - brushMenu->addAction(brushWidthAct); - brushMenu->addSeparator(); - - shapesMenu = menuBar()->addMenu(tr("&Shapes")); - - filterMenu = menuBar()->addMenu(tr("&Filter")); - - menuBar()->addSeparator(); - - helpMenu = menuBar()->addMenu(tr("&Help")); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); - helpMenu->addAction(aboutPluginsAct); -} - -//! [4] -void MainWindow::loadPlugins() -{ - foreach (QObject *plugin, QPluginLoader::staticInstances()) - populateMenus(plugin); -//! [4] //! [5] - - pluginsDir = QDir(qApp->applicationDirPath()); - -#if defined(Q_OS_WIN) - if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") - pluginsDir.cdUp(); -#elif defined(Q_OS_MAC) - if (pluginsDir.dirName() == "MacOS") { - pluginsDir.cdUp(); - pluginsDir.cdUp(); - pluginsDir.cdUp(); - } -#endif - pluginsDir.cd("plugins"); -//! [5] - -//! [6] - foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { - QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); - QObject *plugin = loader.instance(); - if (plugin) { - populateMenus(plugin); - pluginFileNames += fileName; -//! [6] //! [7] - } -//! [7] //! [8] - } -//! [8] - -//! [9] - brushMenu->setEnabled(!brushActionGroup->actions().isEmpty()); - shapesMenu->setEnabled(!shapesMenu->actions().isEmpty()); - filterMenu->setEnabled(!filterMenu->actions().isEmpty()); -} -//! [9] - -//! [10] -void MainWindow::populateMenus(QObject *plugin) -{ - BrushInterface *iBrush = qobject_cast(plugin); - if (iBrush) - addToMenu(plugin, iBrush->brushes(), brushMenu, SLOT(changeBrush()), - brushActionGroup); - - ShapeInterface *iShape = qobject_cast(plugin); - if (iShape) - addToMenu(plugin, iShape->shapes(), shapesMenu, SLOT(insertShape())); - - FilterInterface *iFilter = qobject_cast(plugin); - if (iFilter) - addToMenu(plugin, iFilter->filters(), filterMenu, SLOT(applyFilter())); -} -//! [10] - -void MainWindow::addToMenu(QObject *plugin, const QStringList &texts, - QMenu *menu, const char *member, - QActionGroup *actionGroup) -{ - foreach (QString text, texts) { - QAction *action = new QAction(text, plugin); - connect(action, SIGNAL(triggered()), this, member); - menu->addAction(action); - - if (actionGroup) { - action->setCheckable(true); - actionGroup->addAction(action); - } - } -} diff --git a/examples/widgets/tools/plugandpaint/mainwindow.h b/examples/widgets/tools/plugandpaint/mainwindow.h deleted file mode 100644 index 06f7157d80..0000000000 --- a/examples/widgets/tools/plugandpaint/mainwindow.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QAction; -class QActionGroup; -class QMenu; -class QScrollArea; -QT_END_NAMESPACE -class PaintArea; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(); - -private slots: - void open(); - bool saveAs(); - void brushColor(); - void brushWidth(); - void changeBrush(); - void insertShape(); - void applyFilter(); - void about(); - void aboutPlugins(); - -private: - void createActions(); - void createMenus(); - void loadPlugins(); - void populateMenus(QObject *plugin); - void addToMenu(QObject *plugin, const QStringList &texts, QMenu *menu, - const char *member, QActionGroup *actionGroup = 0); - - PaintArea *paintArea; - QScrollArea *scrollArea; - QDir pluginsDir; - QStringList pluginFileNames; - - QMenu *fileMenu; - QMenu *brushMenu; - QMenu *shapesMenu; - QMenu *filterMenu; - QMenu *helpMenu; - QActionGroup *brushActionGroup; - QAction *openAct; - QAction *saveAsAct; - QAction *exitAct; - QAction *brushWidthAct; - QAction *brushColorAct; - QAction *aboutAct; - QAction *aboutQtAct; - QAction *aboutPluginsAct; -}; - -#endif diff --git a/examples/widgets/tools/plugandpaint/paintarea.cpp b/examples/widgets/tools/plugandpaint/paintarea.cpp deleted file mode 100644 index f5816c6d8e..0000000000 --- a/examples/widgets/tools/plugandpaint/paintarea.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "interfaces.h" -#include "paintarea.h" - -#include -#include - -PaintArea::PaintArea(QWidget *parent) : - QWidget(parent), - theImage(500, 400, QImage::Format_RGB32), - color(Qt::blue), - thickness(3), - brushInterface(0), - lastPos(-1, -1) -{ - setAttribute(Qt::WA_StaticContents); - setAttribute(Qt::WA_NoBackground); - - theImage.fill(qRgb(255, 255, 255)); -} - -bool PaintArea::openImage(const QString &fileName) -{ - QImage image; - if (!image.load(fileName)) - return false; - - setImage(image); - return true; -} - -bool PaintArea::saveImage(const QString &fileName, const char *fileFormat) -{ - return theImage.save(fileName, fileFormat); -} - -void PaintArea::setImage(const QImage &image) -{ - theImage = image.convertToFormat(QImage::Format_RGB32); - update(); - updateGeometry(); -} - -void PaintArea::insertShape(const QPainterPath &path) -{ - pendingPath = path; -#ifndef QT_NO_CURSOR - setCursor(Qt::CrossCursor); -#endif -} - -void PaintArea::setBrushColor(const QColor &color) -{ - this->color = color; -} - -void PaintArea::setBrushWidth(int width) -{ - thickness = width; -} - -//! [0] -void PaintArea::setBrush(BrushInterface *brushInterface, const QString &brush) -{ - this->brushInterface = brushInterface; - this->brush = brush; -} -//! [0] - -QSize PaintArea::sizeHint() const -{ - return theImage.size(); -} - -void PaintArea::paintEvent(QPaintEvent * /* event */) -{ - QPainter painter(this); - painter.drawImage(QPoint(0, 0), theImage); -} - -void PaintArea::mousePressEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) { - if (!pendingPath.isEmpty()) { - QPainter painter(&theImage); - setupPainter(painter); - - const QRectF boundingRect = pendingPath.boundingRect(); - QLinearGradient gradient(boundingRect.topRight(), - boundingRect.bottomLeft()); - gradient.setColorAt(0.0, QColor(color.red(), color.green(), - color.blue(), 63)); - gradient.setColorAt(1.0, QColor(color.red(), color.green(), - color.blue(), 191)); - painter.setBrush(gradient); - painter.translate(event->pos() - boundingRect.center()); - painter.drawPath(pendingPath); - - pendingPath = QPainterPath(); -#ifndef QT_NO_CURSOR - unsetCursor(); -#endif - update(); - } else { - if (brushInterface) { - QPainter painter(&theImage); - setupPainter(painter); - const QRect rect = brushInterface->mousePress(brush, painter, - event->pos()); - update(rect); - } - - lastPos = event->pos(); - } - } -} - -//! [1] -void PaintArea::mouseMoveEvent(QMouseEvent *event) -{ - if ((event->buttons() & Qt::LeftButton) && lastPos != QPoint(-1, -1)) { - if (brushInterface) { - QPainter painter(&theImage); - setupPainter(painter); - const QRect rect = brushInterface->mouseMove(brush, painter, lastPos, - event->pos()); - update(rect); - } - - lastPos = event->pos(); - } -} -//! [1] - -void PaintArea::mouseReleaseEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton && lastPos != QPoint(-1, -1)) { - if (brushInterface) { - QPainter painter(&theImage); - setupPainter(painter); - QRect rect = brushInterface->mouseRelease(brush, painter, - event->pos()); - update(rect); - } - - lastPos = QPoint(-1, -1); - } -} - -void PaintArea::setupPainter(QPainter &painter) -{ - painter.setRenderHint(QPainter::Antialiasing, true); - painter.setPen(QPen(color, thickness, Qt::SolidLine, Qt::RoundCap, - Qt::RoundJoin)); -} diff --git a/examples/widgets/tools/plugandpaint/paintarea.h b/examples/widgets/tools/plugandpaint/paintarea.h deleted file mode 100644 index eb953ff5c2..0000000000 --- a/examples/widgets/tools/plugandpaint/paintarea.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PAINTAREA_H -#define PAINTAREA_H - -#include -#include -#include -#include - -class BrushInterface; - -class PaintArea : public QWidget -{ - Q_OBJECT - -public: - PaintArea(QWidget *parent = 0); - - bool openImage(const QString &fileName); - bool saveImage(const QString &fileName, const char *fileFormat); - void setImage(const QImage &image); - void insertShape(const QPainterPath &path); - void setBrushColor(const QColor &color); - void setBrushWidth(int width); - void setBrush(BrushInterface *brushInterface, const QString &brush); - - QImage image() const { return theImage; } - QColor brushColor() const { return color; } - int brushWidth() const { return thickness; } - QSize sizeHint() const Q_DECL_OVERRIDE; - -protected: - void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; - void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; - -private: - void setupPainter(QPainter &painter); - - QImage theImage; - QColor color; - int thickness; - - BrushInterface *brushInterface; - QString brush; - QPoint lastPos; - - QPainterPath pendingPath; -}; - -#endif diff --git a/examples/widgets/tools/plugandpaint/plugandpaint.pro b/examples/widgets/tools/plugandpaint/plugandpaint.pro index 965eacf388..f7da8a52bd 100644 --- a/examples/widgets/tools/plugandpaint/plugandpaint.pro +++ b/examples/widgets/tools/plugandpaint/plugandpaint.pro @@ -1,23 +1,4 @@ -#! [0] -QT += widgets +TEMPLATE = subdirs +SUBDIRS = plugins app -HEADERS = interfaces.h \ - mainwindow.h \ - paintarea.h \ - plugindialog.h -SOURCES = main.cpp \ - mainwindow.cpp \ - paintarea.cpp \ - plugindialog.cpp - -LIBS = -Lplugins -lpnp_basictools - -if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { - mac:LIBS = $$member(LIBS, 0) $$member(LIBS, 1)_debug - win32:LIBS = $$member(LIBS, 0) $$member(LIBS, 1)d -} -#! [0] - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint -INSTALLS += target +app.depends = plugins diff --git a/examples/widgets/tools/plugandpaint/plugindialog.cpp b/examples/widgets/tools/plugandpaint/plugindialog.cpp deleted file mode 100644 index e6ac586c6d..0000000000 --- a/examples/widgets/tools/plugandpaint/plugindialog.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "interfaces.h" -#include "plugindialog.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -PluginDialog::PluginDialog(const QString &path, const QStringList &fileNames, - QWidget *parent) : - QDialog(parent), - label(new QLabel), - treeWidget(new QTreeWidget), - okButton(new QPushButton(tr("OK"))) -{ - treeWidget->setAlternatingRowColors(false); - treeWidget->setSelectionMode(QAbstractItemView::NoSelection); - treeWidget->setColumnCount(1); - treeWidget->header()->hide(); - - okButton->setDefault(true); - - connect(okButton, SIGNAL(clicked()), this, SLOT(close())); - - QGridLayout *mainLayout = new QGridLayout; - mainLayout->setColumnStretch(0, 1); - mainLayout->setColumnStretch(2, 1); - mainLayout->addWidget(label, 0, 0, 1, 3); - mainLayout->addWidget(treeWidget, 1, 0, 1, 3); - mainLayout->addWidget(okButton, 2, 1); - setLayout(mainLayout); - - interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon), - QIcon::Normal, QIcon::On); - interfaceIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon), - QIcon::Normal, QIcon::Off); - featureIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon)); - - setWindowTitle(tr("Plugin Information")); - findPlugins(path, fileNames); -} - -//! [0] -void PluginDialog::findPlugins(const QString &path, - const QStringList &fileNames) -{ - label->setText(tr("Plug & Paint found the following plugins\n" - "(looked in %1):") - .arg(QDir::toNativeSeparators(path))); - - const QDir dir(path); - - foreach (QObject *plugin, QPluginLoader::staticInstances()) - populateTreeWidget(plugin, tr("%1 (Static Plugin)") - .arg(plugin->metaObject()->className())); - - foreach (QString fileName, fileNames) { - QPluginLoader loader(dir.absoluteFilePath(fileName)); - QObject *plugin = loader.instance(); - if (plugin) - populateTreeWidget(plugin, fileName); - } -} -//! [0] - -//! [1] -void PluginDialog::populateTreeWidget(QObject *plugin, const QString &text) -{ - QTreeWidgetItem *pluginItem = new QTreeWidgetItem(treeWidget); - pluginItem->setText(0, text); - treeWidget->setItemExpanded(pluginItem, true); - - QFont boldFont = pluginItem->font(0); - boldFont.setBold(true); - pluginItem->setFont(0, boldFont); - - if (plugin) { - BrushInterface *iBrush = qobject_cast(plugin); - if (iBrush) - addItems(pluginItem, "BrushInterface", iBrush->brushes()); - - ShapeInterface *iShape = qobject_cast(plugin); - if (iShape) - addItems(pluginItem, "ShapeInterface", iShape->shapes()); - - FilterInterface *iFilter = - qobject_cast(plugin); - if (iFilter) - addItems(pluginItem, "FilterInterface", iFilter->filters()); - } -} -//! [1] - -void PluginDialog::addItems(QTreeWidgetItem *pluginItem, - const char *interfaceName, - const QStringList &features) -{ - QTreeWidgetItem *interfaceItem = new QTreeWidgetItem(pluginItem); - interfaceItem->setText(0, interfaceName); - interfaceItem->setIcon(0, interfaceIcon); - - foreach (QString feature, features) { - if (feature.endsWith("...")) - feature.chop(3); - QTreeWidgetItem *featureItem = new QTreeWidgetItem(interfaceItem); - featureItem->setText(0, feature); - featureItem->setIcon(0, featureIcon); - } -} diff --git a/examples/widgets/tools/plugandpaint/plugindialog.h b/examples/widgets/tools/plugandpaint/plugindialog.h deleted file mode 100644 index f235d09c31..0000000000 --- a/examples/widgets/tools/plugandpaint/plugindialog.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PLUGINDIALOG_H -#define PLUGINDIALOG_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QLabel; -class QPushButton; -class QStringList; -class QTreeWidget; -class QTreeWidgetItem; -QT_END_NAMESPACE - -class PluginDialog : public QDialog -{ - Q_OBJECT - -public: - PluginDialog(const QString &path, const QStringList &fileNames, - QWidget *parent = 0); - -private: - void findPlugins(const QString &path, const QStringList &fileNames); - void populateTreeWidget(QObject *plugin, const QString &text); - void addItems(QTreeWidgetItem *pluginItem, const char *interfaceName, - const QStringList &features); - - QLabel *label; - QTreeWidget *treeWidget; - QPushButton *okButton; - QIcon interfaceIcon; - QIcon featureIcon; -}; - -#endif diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.json b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.json @@ -0,0 +1 @@ +{} diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro new file mode 100644 index 0000000000..0c0a262339 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro @@ -0,0 +1,14 @@ +#! [0] +TEMPLATE = lib +CONFIG += plugin static +QT += widgets +INCLUDEPATH += ../../app +HEADERS = basictoolsplugin.h +SOURCES = basictoolsplugin.cpp +TARGET = $$qtLibraryTarget(pnp_basictools) +DESTDIR = ../../plugins +#! [0] + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins +INSTALLS += target diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp new file mode 100644 index 0000000000..a5ca14a39c --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include + +#include "basictoolsplugin.h" + +const float Pi = 3.14159f; + +//! [0] +QStringList BasicToolsPlugin::brushes() const +{ + return QStringList() << tr("Pencil") << tr("Air Brush") + << tr("Random Letters"); +} +//! [0] + +//! [1] +QRect BasicToolsPlugin::mousePress(const QString &brush, QPainter &painter, + const QPoint &pos) +{ + return mouseMove(brush, painter, pos, pos); +} +//! [1] + +//! [2] +QRect BasicToolsPlugin::mouseMove(const QString &brush, QPainter &painter, + const QPoint &oldPos, const QPoint &newPos) +{ + painter.save(); + + int rad = painter.pen().width() / 2; + QRect boundingRect = QRect(oldPos, newPos).normalized() + .adjusted(-rad, -rad, +rad, +rad); + QColor color = painter.pen().color(); + int thickness = painter.pen().width(); + QColor transparentColor(color.red(), color.green(), color.blue(), 0); +//! [2] //! [3] + + if (brush == tr("Pencil")) { + painter.drawLine(oldPos, newPos); + } else if (brush == tr("Air Brush")) { + int numSteps = 2 + (newPos - oldPos).manhattanLength() / 2; + + painter.setBrush(QBrush(color, Qt::Dense6Pattern)); + painter.setPen(Qt::NoPen); + + for (int i = 0; i < numSteps; ++i) { + int x = oldPos.x() + i * (newPos.x() - oldPos.x()) / (numSteps - 1); + int y = oldPos.y() + i * (newPos.y() - oldPos.y()) / (numSteps - 1); + + painter.drawEllipse(x - (thickness / 2), y - (thickness / 2), + thickness, thickness); + } + } else if (brush == tr("Random Letters")) { + QChar ch('A' + (qrand() % 26)); + + QFont biggerFont = painter.font(); + biggerFont.setBold(true); + biggerFont.setPointSize(biggerFont.pointSize() + thickness); + painter.setFont(biggerFont); + + painter.drawText(newPos, QString(ch)); + + QFontMetrics metrics(painter.font()); + boundingRect = metrics.boundingRect(ch); + boundingRect.translate(newPos); + boundingRect.adjust(-10, -10, +10, +10); + } + painter.restore(); + return boundingRect; +} +//! [3] + +//! [4] +QRect BasicToolsPlugin::mouseRelease(const QString & /* brush */, + QPainter & /* painter */, + const QPoint & /* pos */) +{ + return QRect(0, 0, 0, 0); +} +//! [4] + +//! [5] +QStringList BasicToolsPlugin::shapes() const +{ + return QStringList() << tr("Circle") << tr("Star") << tr("Text..."); +} +//! [5] + +//! [6] +QPainterPath BasicToolsPlugin::generateShape(const QString &shape, + QWidget *parent) +{ + QPainterPath path; + + if (shape == tr("Circle")) { + path.addEllipse(0, 0, 50, 50); + } else if (shape == tr("Star")) { + path.moveTo(90, 50); + for (int i = 1; i < 5; ++i) { + path.lineTo(50 + 40 * std::cos(0.8 * i * Pi), + 50 + 40 * std::sin(0.8 * i * Pi)); + } + path.closeSubpath(); + } else if (shape == tr("Text...")) { + QString text = QInputDialog::getText(parent, tr("Text Shape"), + tr("Enter text:"), + QLineEdit::Normal, tr("Qt")); + if (!text.isEmpty()) { + QFont timesFont("Times", 50); + timesFont.setStyleStrategy(QFont::ForceOutline); + path.addText(0, 0, timesFont, text); + } + } + + return path; +} +//! [6] + +//! [7] +QStringList BasicToolsPlugin::filters() const +{ + return QStringList() << tr("Invert Pixels") << tr("Swap RGB") + << tr("Grayscale"); +} +//! [7] + +//! [8] +QImage BasicToolsPlugin::filterImage(const QString &filter, const QImage &image, + QWidget * /* parent */) +{ + QImage result = image.convertToFormat(QImage::Format_RGB32); + + if (filter == tr("Invert Pixels")) { + result.invertPixels(); + } else if (filter == tr("Swap RGB")) { + result = result.rgbSwapped(); + } else if (filter == tr("Grayscale")) { + for (int y = 0; y < result.height(); ++y) { + for (int x = 0; x < result.width(); ++x) { + int pixel = result.pixel(x, y); + int gray = qGray(pixel); + int alpha = qAlpha(pixel); + result.setPixel(x, y, qRgba(gray, gray, gray, alpha)); + } + } + } + return result; +} +//! [8] diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h new file mode 100644 index 0000000000..d701c8357e --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BASICTOOLSPLUGIN_H +#define BASICTOOLSPLUGIN_H + +//! [0] +#include + +#include +#include +#include +#include +#include +#include + +//! [1] +class BasicToolsPlugin : public QObject, + public BrushInterface, + public ShapeInterface, + public FilterInterface +{ + Q_OBJECT +//! [4] + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json") +//! [4] + Q_INTERFACES(BrushInterface ShapeInterface FilterInterface) +//! [0] + +//! [2] +public: +//! [1] + // BrushInterface + QStringList brushes() const Q_DECL_OVERRIDE; + QRect mousePress(const QString &brush, QPainter &painter, + const QPoint &pos) Q_DECL_OVERRIDE; + QRect mouseMove(const QString &brush, QPainter &painter, + const QPoint &oldPos, const QPoint &newPos) Q_DECL_OVERRIDE; + QRect mouseRelease(const QString &brush, QPainter &painter, + const QPoint &pos) Q_DECL_OVERRIDE; + + // ShapeInterface + QStringList shapes() const Q_DECL_OVERRIDE; + QPainterPath generateShape(const QString &shape, QWidget *parent) Q_DECL_OVERRIDE; + + // FilterInterface + QStringList filters() const Q_DECL_OVERRIDE; + QImage filterImage(const QString &filter, const QImage &image, + QWidget *parent) Q_DECL_OVERRIDE; +//! [3] +}; +//! [2] //! [3] + +#endif diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.json b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.json @@ -0,0 +1 @@ +{} diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro new file mode 100644 index 0000000000..0c86a575f3 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro @@ -0,0 +1,14 @@ +#! [0] +TEMPLATE = lib +CONFIG += plugin +QT += widgets +INCLUDEPATH += ../../app +HEADERS = extrafiltersplugin.h +SOURCES = extrafiltersplugin.cpp +TARGET = $$qtLibraryTarget(pnp_extrafilters) +DESTDIR = ../../plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins +INSTALLS += target diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.cpp b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.cpp new file mode 100644 index 0000000000..bce8291a60 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.cpp @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include + +#include "extrafiltersplugin.h" + +QStringList ExtraFiltersPlugin::filters() const +{ + return QStringList() << tr("Flip Horizontally") << tr("Flip Vertically") + << tr("Smudge...") << tr("Threshold..."); +} + +QImage ExtraFiltersPlugin::filterImage(const QString &filter, + const QImage &image, QWidget *parent) +{ + QImage original = image.convertToFormat(QImage::Format_RGB32); + QImage result = original; + + if (filter == tr("Flip Horizontally")) { + for (int y = 0; y < original.height(); ++y) { + for (int x = 0; x < original.width(); ++x) { + int pixel = original.pixel(original.width() - x - 1, y); + result.setPixel(x, y, pixel); + } + } + } else if (filter == tr("Flip Vertically")) { + for (int y = 0; y < original.height(); ++y) { + for (int x = 0; x < original.width(); ++x) { + int pixel = original.pixel(x, original.height() - y - 1); + result.setPixel(x, y, pixel); + } + } + } else if (filter == tr("Smudge...")) { + bool ok; + int numIters = QInputDialog::getInt(parent, tr("Smudge Filter"), + tr("Enter number of iterations:"), + 5, 1, 20, 1, &ok); + if (ok) { + for (int i = 0; i < numIters; ++i) { + for (int y = 1; y < original.height() - 1; ++y) { + for (int x = 1; x < original.width() - 1; ++x) { + int p1 = original.pixel(x, y); + int p2 = original.pixel(x, y + 1); + int p3 = original.pixel(x, y - 1); + int p4 = original.pixel(x + 1, y); + int p5 = original.pixel(x - 1, y); + + int red = (qRed(p1) + qRed(p2) + qRed(p3) + qRed(p4) + + qRed(p5)) / 5; + int green = (qGreen(p1) + qGreen(p2) + qGreen(p3) + + qGreen(p4) + qGreen(p5)) / 5; + int blue = (qBlue(p1) + qBlue(p2) + qBlue(p3) + + qBlue(p4) + qBlue(p5)) / 5; + int alpha = (qAlpha(p1) + qAlpha(p2) + qAlpha(p3) + + qAlpha(p4) + qAlpha(p5)) / 5; + + result.setPixel(x, y, qRgba(red, green, blue, alpha)); + } + } + } + } + } else if (filter == tr("Threshold...")) { + bool ok; + int threshold = QInputDialog::getInt(parent, tr("Threshold Filter"), + tr("Enter threshold:"), + 10, 1, 256, 1, &ok); + if (ok) { + int factor = 256 / threshold; + for (int y = 0; y < original.height(); ++y) { + for (int x = 0; x < original.width(); ++x) { + int pixel = original.pixel(x, y); + result.setPixel(x, y, qRgba(qRed(pixel) / factor * factor, + qGreen(pixel) / factor * factor, + qBlue(pixel) / factor * factor, + qAlpha(pixel))); + } + } + } + } + return result; +} diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.h b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.h new file mode 100644 index 0000000000..837f1a9c7f --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafiltersplugin.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EXTRAFILTERSPLUGIN_H +#define EXTRAFILTERSPLUGIN_H + +//! [0] +#include + +#include +#include +#include +#include + +class ExtraFiltersPlugin : public QObject, public FilterInterface +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json") + Q_INTERFACES(FilterInterface) + +public: + QStringList filters() const Q_DECL_OVERRIDE; + QImage filterImage(const QString &filter, const QImage &image, + QWidget *parent) Q_DECL_OVERRIDE; +}; +//! [0] + +#endif diff --git a/examples/widgets/tools/plugandpaint/plugins/plugins.pro b/examples/widgets/tools/plugandpaint/plugins/plugins.pro new file mode 100644 index 0000000000..e15220c621 --- /dev/null +++ b/examples/widgets/tools/plugandpaint/plugins/plugins.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS = basictools \ + extrafilters diff --git a/examples/widgets/tools/plugandpaintplugins/basictools/basictools.json b/examples/widgets/tools/plugandpaintplugins/basictools/basictools.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/basictools/basictools.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/examples/widgets/tools/plugandpaintplugins/basictools/basictools.pro b/examples/widgets/tools/plugandpaintplugins/basictools/basictools.pro deleted file mode 100644 index 670ebb5709..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/basictools/basictools.pro +++ /dev/null @@ -1,14 +0,0 @@ -#! [0] -TEMPLATE = lib -CONFIG += plugin static -QT += widgets -INCLUDEPATH += ../.. -HEADERS = basictoolsplugin.h -SOURCES = basictoolsplugin.cpp -TARGET = $$qtLibraryTarget(pnp_basictools) -DESTDIR = ../../plugandpaint/plugins -#! [0] - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins -INSTALLS += target diff --git a/examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp b/examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp deleted file mode 100644 index a5ca14a39c..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include -#include - -#include "basictoolsplugin.h" - -const float Pi = 3.14159f; - -//! [0] -QStringList BasicToolsPlugin::brushes() const -{ - return QStringList() << tr("Pencil") << tr("Air Brush") - << tr("Random Letters"); -} -//! [0] - -//! [1] -QRect BasicToolsPlugin::mousePress(const QString &brush, QPainter &painter, - const QPoint &pos) -{ - return mouseMove(brush, painter, pos, pos); -} -//! [1] - -//! [2] -QRect BasicToolsPlugin::mouseMove(const QString &brush, QPainter &painter, - const QPoint &oldPos, const QPoint &newPos) -{ - painter.save(); - - int rad = painter.pen().width() / 2; - QRect boundingRect = QRect(oldPos, newPos).normalized() - .adjusted(-rad, -rad, +rad, +rad); - QColor color = painter.pen().color(); - int thickness = painter.pen().width(); - QColor transparentColor(color.red(), color.green(), color.blue(), 0); -//! [2] //! [3] - - if (brush == tr("Pencil")) { - painter.drawLine(oldPos, newPos); - } else if (brush == tr("Air Brush")) { - int numSteps = 2 + (newPos - oldPos).manhattanLength() / 2; - - painter.setBrush(QBrush(color, Qt::Dense6Pattern)); - painter.setPen(Qt::NoPen); - - for (int i = 0; i < numSteps; ++i) { - int x = oldPos.x() + i * (newPos.x() - oldPos.x()) / (numSteps - 1); - int y = oldPos.y() + i * (newPos.y() - oldPos.y()) / (numSteps - 1); - - painter.drawEllipse(x - (thickness / 2), y - (thickness / 2), - thickness, thickness); - } - } else if (brush == tr("Random Letters")) { - QChar ch('A' + (qrand() % 26)); - - QFont biggerFont = painter.font(); - biggerFont.setBold(true); - biggerFont.setPointSize(biggerFont.pointSize() + thickness); - painter.setFont(biggerFont); - - painter.drawText(newPos, QString(ch)); - - QFontMetrics metrics(painter.font()); - boundingRect = metrics.boundingRect(ch); - boundingRect.translate(newPos); - boundingRect.adjust(-10, -10, +10, +10); - } - painter.restore(); - return boundingRect; -} -//! [3] - -//! [4] -QRect BasicToolsPlugin::mouseRelease(const QString & /* brush */, - QPainter & /* painter */, - const QPoint & /* pos */) -{ - return QRect(0, 0, 0, 0); -} -//! [4] - -//! [5] -QStringList BasicToolsPlugin::shapes() const -{ - return QStringList() << tr("Circle") << tr("Star") << tr("Text..."); -} -//! [5] - -//! [6] -QPainterPath BasicToolsPlugin::generateShape(const QString &shape, - QWidget *parent) -{ - QPainterPath path; - - if (shape == tr("Circle")) { - path.addEllipse(0, 0, 50, 50); - } else if (shape == tr("Star")) { - path.moveTo(90, 50); - for (int i = 1; i < 5; ++i) { - path.lineTo(50 + 40 * std::cos(0.8 * i * Pi), - 50 + 40 * std::sin(0.8 * i * Pi)); - } - path.closeSubpath(); - } else if (shape == tr("Text...")) { - QString text = QInputDialog::getText(parent, tr("Text Shape"), - tr("Enter text:"), - QLineEdit::Normal, tr("Qt")); - if (!text.isEmpty()) { - QFont timesFont("Times", 50); - timesFont.setStyleStrategy(QFont::ForceOutline); - path.addText(0, 0, timesFont, text); - } - } - - return path; -} -//! [6] - -//! [7] -QStringList BasicToolsPlugin::filters() const -{ - return QStringList() << tr("Invert Pixels") << tr("Swap RGB") - << tr("Grayscale"); -} -//! [7] - -//! [8] -QImage BasicToolsPlugin::filterImage(const QString &filter, const QImage &image, - QWidget * /* parent */) -{ - QImage result = image.convertToFormat(QImage::Format_RGB32); - - if (filter == tr("Invert Pixels")) { - result.invertPixels(); - } else if (filter == tr("Swap RGB")) { - result = result.rgbSwapped(); - } else if (filter == tr("Grayscale")) { - for (int y = 0; y < result.height(); ++y) { - for (int x = 0; x < result.width(); ++x) { - int pixel = result.pixel(x, y); - int gray = qGray(pixel); - int alpha = qAlpha(pixel); - result.setPixel(x, y, qRgba(gray, gray, gray, alpha)); - } - } - } - return result; -} -//! [8] diff --git a/examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h b/examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h deleted file mode 100644 index 3cf4e8ff11..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BASICTOOLSPLUGIN_H -#define BASICTOOLSPLUGIN_H - -#include -#include -#include -#include -#include -#include - -//! [0] -#include - -//! [1] -class BasicToolsPlugin : public QObject, - public BrushInterface, - public ShapeInterface, - public FilterInterface -{ - Q_OBJECT -//! [4] - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.BrushInterface" FILE "basictools.json") -//! [4] - Q_INTERFACES(BrushInterface ShapeInterface FilterInterface) -//! [0] - -//! [2] -public: -//! [1] - // BrushInterface - QStringList brushes() const Q_DECL_OVERRIDE; - QRect mousePress(const QString &brush, QPainter &painter, - const QPoint &pos) Q_DECL_OVERRIDE; - QRect mouseMove(const QString &brush, QPainter &painter, - const QPoint &oldPos, const QPoint &newPos) Q_DECL_OVERRIDE; - QRect mouseRelease(const QString &brush, QPainter &painter, - const QPoint &pos) Q_DECL_OVERRIDE; - - // ShapeInterface - QStringList shapes() const Q_DECL_OVERRIDE; - QPainterPath generateShape(const QString &shape, QWidget *parent) Q_DECL_OVERRIDE; - - // FilterInterface - QStringList filters() const Q_DECL_OVERRIDE; - QImage filterImage(const QString &filter, const QImage &image, - QWidget *parent) Q_DECL_OVERRIDE; -//! [3] -}; -//! [2] //! [3] - -#endif diff --git a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.json b/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.pro b/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.pro deleted file mode 100644 index aa0ead87bc..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafilters.pro +++ /dev/null @@ -1,14 +0,0 @@ -#! [0] -TEMPLATE = lib -CONFIG += plugin -QT += widgets -INCLUDEPATH += ../.. -HEADERS = extrafiltersplugin.h -SOURCES = extrafiltersplugin.cpp -TARGET = $$qtLibraryTarget(pnp_extrafilters) -DESTDIR = ../../plugandpaint/plugins - -#! [0] -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins -INSTALLS += target diff --git a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.cpp b/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.cpp deleted file mode 100644 index bce8291a60..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include -#include - -#include "extrafiltersplugin.h" - -QStringList ExtraFiltersPlugin::filters() const -{ - return QStringList() << tr("Flip Horizontally") << tr("Flip Vertically") - << tr("Smudge...") << tr("Threshold..."); -} - -QImage ExtraFiltersPlugin::filterImage(const QString &filter, - const QImage &image, QWidget *parent) -{ - QImage original = image.convertToFormat(QImage::Format_RGB32); - QImage result = original; - - if (filter == tr("Flip Horizontally")) { - for (int y = 0; y < original.height(); ++y) { - for (int x = 0; x < original.width(); ++x) { - int pixel = original.pixel(original.width() - x - 1, y); - result.setPixel(x, y, pixel); - } - } - } else if (filter == tr("Flip Vertically")) { - for (int y = 0; y < original.height(); ++y) { - for (int x = 0; x < original.width(); ++x) { - int pixel = original.pixel(x, original.height() - y - 1); - result.setPixel(x, y, pixel); - } - } - } else if (filter == tr("Smudge...")) { - bool ok; - int numIters = QInputDialog::getInt(parent, tr("Smudge Filter"), - tr("Enter number of iterations:"), - 5, 1, 20, 1, &ok); - if (ok) { - for (int i = 0; i < numIters; ++i) { - for (int y = 1; y < original.height() - 1; ++y) { - for (int x = 1; x < original.width() - 1; ++x) { - int p1 = original.pixel(x, y); - int p2 = original.pixel(x, y + 1); - int p3 = original.pixel(x, y - 1); - int p4 = original.pixel(x + 1, y); - int p5 = original.pixel(x - 1, y); - - int red = (qRed(p1) + qRed(p2) + qRed(p3) + qRed(p4) - + qRed(p5)) / 5; - int green = (qGreen(p1) + qGreen(p2) + qGreen(p3) - + qGreen(p4) + qGreen(p5)) / 5; - int blue = (qBlue(p1) + qBlue(p2) + qBlue(p3) - + qBlue(p4) + qBlue(p5)) / 5; - int alpha = (qAlpha(p1) + qAlpha(p2) + qAlpha(p3) - + qAlpha(p4) + qAlpha(p5)) / 5; - - result.setPixel(x, y, qRgba(red, green, blue, alpha)); - } - } - } - } - } else if (filter == tr("Threshold...")) { - bool ok; - int threshold = QInputDialog::getInt(parent, tr("Threshold Filter"), - tr("Enter threshold:"), - 10, 1, 256, 1, &ok); - if (ok) { - int factor = 256 / threshold; - for (int y = 0; y < original.height(); ++y) { - for (int x = 0; x < original.width(); ++x) { - int pixel = original.pixel(x, y); - result.setPixel(x, y, qRgba(qRed(pixel) / factor * factor, - qGreen(pixel) / factor * factor, - qBlue(pixel) / factor * factor, - qAlpha(pixel))); - } - } - } - } - return result; -} diff --git a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.h b/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.h deleted file mode 100644 index 79cf083794..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/extrafilters/extrafiltersplugin.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef EXTRAFILTERSPLUGIN_H -#define EXTRAFILTERSPLUGIN_H - -//! [0] -#include -#include -#include -#include - -#include - -class ExtraFiltersPlugin : public QObject, public FilterInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PlugAndPaint.FilterInterface" FILE "extrafilters.json") - Q_INTERFACES(FilterInterface) - -public: - QStringList filters() const Q_DECL_OVERRIDE; - QImage filterImage(const QString &filter, const QImage &image, - QWidget *parent) Q_DECL_OVERRIDE; -}; -//! [0] - -#endif diff --git a/examples/widgets/tools/plugandpaintplugins/plugandpaintplugins.pro b/examples/widgets/tools/plugandpaintplugins/plugandpaintplugins.pro deleted file mode 100644 index e15220c621..0000000000 --- a/examples/widgets/tools/plugandpaintplugins/plugandpaintplugins.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = basictools \ - extrafilters diff --git a/examples/widgets/tools/tools.pro b/examples/widgets/tools/tools.pro index 282f8dedea..69a37f342c 100644 --- a/examples/widgets/tools/tools.pro +++ b/examples/widgets/tools/tools.pro @@ -5,7 +5,6 @@ SUBDIRS = \ customcompleter \ echoplugin \ i18n \ - plugandpaintplugins \ plugandpaint \ regexp \ regularexpression \ @@ -16,5 +15,3 @@ SUBDIRS = \ undoframework contains(DEFINES, QT_NO_TRANSLATION): SUBDIRS -= i18n - -plugandpaint.depends = plugandpaintplugins diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 19df24744a..d97f8d0ef1 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1123,7 +1123,7 @@ QObjectPrivate::Connection::~Connection() RTTI support and it works across dynamic library boundaries. qobject_cast() can also be used in conjunction with interfaces; - see the \l{tools/plugandpaint}{Plug & Paint} example for details. + see the \l{tools/plugandpaint/app}{Plug & Paint} example for details. \warning If T isn't declared with the Q_OBJECT macro, this function's return value is undefined. @@ -4150,11 +4150,11 @@ QDebug operator<<(QDebug dbg, const QObject *o) Example: - \snippet ../widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h 1 + \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 1 \dots - \snippet ../widgets/tools/plugandpaintplugins/basictools/basictoolsplugin.h 3 + \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 3 - See the \l{tools/plugandpaintplugins/basictools}{Plug & Paint + See the \l{tools/plugandpaint/plugins/basictools}{Plug & Paint Basic Tools} example for details. \sa Q_DECLARE_INTERFACE(), Q_PLUGIN_METADATA(), {How to Create Qt Plugins} diff --git a/src/corelib/plugin/qplugin.qdoc b/src/corelib/plugin/qplugin.qdoc index 1b394c4174..09eed5a1e6 100644 --- a/src/corelib/plugin/qplugin.qdoc +++ b/src/corelib/plugin/qplugin.qdoc @@ -44,11 +44,11 @@ to the interface class called \a ClassName. The \a Identifier must be unique. For example: - \snippet plugandpaint/interfaces.h 3 + \snippet plugandpaint/app/interfaces.h 3 This macro is normally used right after the class definition for \a ClassName, in a header file. See the - \l{tools/plugandpaint}{Plug & Paint} example for details. + \l{tools/plugandpaint/app}{Plug & Paint} example for details. If you want to use Q_DECLARE_INTERFACE with interface classes declared in a namespace then you have to make sure the Q_DECLARE_INTERFACE @@ -76,7 +76,7 @@ \snippet code/doc_src_qplugin.cpp 1 - See the \l{tools/plugandpaint}{Plug & Paint} example for details. + See the \l{tools/plugandpaint/app}{Plug & Paint} example for details. Note that the class this macro appears on must be default-constructible. -- cgit v1.2.3 From 619ab8080dfc4e0908552e71ee2ae19db6ab2c9c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 21 Apr 2016 16:19:52 +0200 Subject: fix build and installation of queuedcustomtype example it was not built at all (and didn't build with qt in a namespace), and consequently was not installed as well. Change-Id: I24d8ac4dd5d70927c262ad6336e5ee32a0fd003a Reviewed-by: Olivier Goffart (Woboq GmbH) --- examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro | 2 +- examples/corelib/threads/queuedcustomtype/window.h | 2 ++ examples/corelib/threads/threads.pro | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro index 77421eb638..8b91fb9ac7 100644 --- a/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro +++ b/examples/corelib/threads/queuedcustomtype/queuedcustomtype.pro @@ -8,7 +8,7 @@ SOURCES = main.cpp \ QT += widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/mandelbrot +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/queuedcustomtype INSTALLS += target diff --git a/examples/corelib/threads/queuedcustomtype/window.h b/examples/corelib/threads/queuedcustomtype/window.h index b1e578faa0..52c67428dd 100644 --- a/examples/corelib/threads/queuedcustomtype/window.h +++ b/examples/corelib/threads/queuedcustomtype/window.h @@ -44,8 +44,10 @@ #include #include "renderthread.h" +QT_BEGIN_NAMESPACE class QLabel; class QPushButton; +QT_END_NAMESPACE //! [Window class definition] class Window : public QWidget diff --git a/examples/corelib/threads/threads.pro b/examples/corelib/threads/threads.pro index e47da84a06..b9e17a8430 100644 --- a/examples/corelib/threads/threads.pro +++ b/examples/corelib/threads/threads.pro @@ -4,4 +4,6 @@ CONFIG += no_docs_target SUBDIRS = semaphores \ waitconditions -qtHaveModule(widgets): SUBDIRS += mandelbrot +qtHaveModule(widgets): SUBDIRS += \ + mandelbrot \ + queuedcustomtype -- cgit v1.2.3 From 2c7b3726bf7fe8ec1516e2327c2a5d046ccdb8fc Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 21 Apr 2016 16:05:45 +0200 Subject: install the opengl legacy examples while they are not built, their sources should be installed as long we don't delete them completely. Change-Id: I5e628e96cc9715520cb6e5aadb2cae61d1d03a4f Reviewed-by: Laszlo Agocs --- examples/opengl/opengl.pro | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/opengl/opengl.pro b/examples/opengl/opengl.pro index ed8134743b..a102e08733 100644 --- a/examples/opengl/opengl.pro +++ b/examples/opengl/opengl.pro @@ -16,3 +16,6 @@ qtHaveModule(widgets) { textures \ hellogles3 } + +EXAMPLE_FILES += \ + legacy -- cgit v1.2.3 From 1ae1f0da0d3b39fe5477161b1e70a7960c4785e3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 21 Apr 2016 16:14:17 +0200 Subject: delete unreferenced file Change-Id: Ibc70cafdc098ff4f6036182d6f41a2debb15a996 Reviewed-by: Joerg Bornemann --- examples/qtestlib/tutorial5/containers.cpp | 264 ----------------------------- 1 file changed, 264 deletions(-) delete mode 100644 examples/qtestlib/tutorial5/containers.cpp diff --git a/examples/qtestlib/tutorial5/containers.cpp b/examples/qtestlib/tutorial5/containers.cpp deleted file mode 100644 index 401a2c54fa..0000000000 --- a/examples/qtestlib/tutorial5/containers.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -// This file contains benchmarks for comparing QVector against std::vector - -#include -#include -#include - -#include - -template // T is the item type -class UseCases { -public: - virtual ~UseCases() {} - - // Use case: Insert \a size items into the vector. - virtual void insert(int size) = 0; - - // Use case: Lookup \a size items from the vector. - virtual void lookup(int size) = 0; -}; - -template -T * f(T *ts) // dummy function to prevent code from being optimized away by the compiler -{ - return ts; -} - -// This subclass implements the use cases using QVector as efficiently as possible. -template -class UseCases_QVector : public UseCases -{ - void insert(int size) - { - QVector v; - T t; - QBENCHMARK { - for (int i = 0; i < size; ++i) - v.append(t); - } - } - - void lookup(int size) - { - QVector v; - - T t; - for (int i = 0; i < size; ++i) - v.append(t); - - T *ts = new T[size]; - QBENCHMARK { - for (int i = 0; i < size; ++i) - ts[i] = v.value(i); - } - f(ts); - delete[] ts; - } -}; - -// This subclass implements the use cases using std::vector as efficiently as possible. -template -class UseCases_stdvector : public UseCases -{ - void insert(int size) - { - std::vector v; - T t; - QBENCHMARK { - for (int i = 0; i < size; ++i) - v.push_back(t); - } - } - - void lookup(int size) - { - std::vector v; - - T t; - for (int i = 0; i < size; ++i) - v.push_back(t); - - T *ts = new T[size]; - QBENCHMARK { - for (int i = 0; i < size; ++i) - ts[i] = v[i]; - } - f(ts); - delete[] ts; - } -}; - -struct Large { // A "large" item type - int x[1000]; -}; - -// Symbian devices typically have limited memory -# define LARGE_MAX_SIZE 20000 - -class tst_vector_vs_std : public QObject -{ - Q_OBJECT -public: - tst_vector_vs_std() - { - useCases_QVector_int = new UseCases_QVector; - useCases_stdvector_int = new UseCases_stdvector; - - useCases_QVector_Large = new UseCases_QVector; - useCases_stdvector_Large = new UseCases_stdvector; - } - -private: - UseCases *useCases_QVector_int; - UseCases *useCases_stdvector_int; - UseCases *useCases_QVector_Large; - UseCases *useCases_stdvector_Large; - -private slots: - void insert_int_data(); - void insert_int(); - void insert_Large_data(); - void insert_Large(); - void lookup_int_data(); - void lookup_int(); - void lookup_Large_data(); - void lookup_Large(); -}; - -void tst_vector_vs_std::insert_int_data() -{ - QTest::addColumn("useStd"); - QTest::addColumn("size"); - - for (int size = 10; size < 20000; size += 100) { - const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-int--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-int--" + sizeString).constData()) << false << size; - } -} - -void tst_vector_vs_std::insert_int() -{ - QFETCH(bool, useStd); - QFETCH(int, size); - - if (useStd) - useCases_stdvector_int->insert(size); - else - useCases_QVector_int->insert(size); -} - -void tst_vector_vs_std::insert_Large_data() -{ - QTest::addColumn("useStd"); - QTest::addColumn("size"); - - for (int size = 10; size < LARGE_MAX_SIZE; size += 100) { - const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-Large--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-Large--" + sizeString).constData()) << false << size; - } -} - -void tst_vector_vs_std::insert_Large() -{ - QFETCH(bool, useStd); - QFETCH(int, size); - - if (useStd) - useCases_stdvector_Large->insert(size); - else - useCases_QVector_Large->insert(size); -} - -//! [1] -void tst_vector_vs_std::lookup_int_data() -{ - QTest::addColumn("useStd"); - QTest::addColumn("size"); - - for (int size = 10; size < 20000; size += 100) { - const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-int--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-int--" + sizeString).constData()) << false << size; - } -} -//! [1] - -//! [2] -void tst_vector_vs_std::lookup_int() -{ - QFETCH(bool, useStd); - QFETCH(int, size); - - if (useStd) - useCases_stdvector_int->lookup(size); // Create a std::vector and run the benchmark. - else - useCases_QVector_int->lookup(size); // Create a QVector and run the benchmark. -} -//! [2] - -void tst_vector_vs_std::lookup_Large_data() -{ - QTest::addColumn("useStd"); - QTest::addColumn("size"); - - for (int size = 10; size < LARGE_MAX_SIZE; size += 100) { - const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-Large--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-Large--" + sizeString).constData()) << false << size; - } -} - -void tst_vector_vs_std::lookup_Large() -{ - QFETCH(bool, useStd); - QFETCH(int, size); - - if (useStd) - useCases_stdvector_Large->lookup(size); - else - useCases_QVector_Large->lookup(size); -} - -QTEST_MAIN(tst_vector_vs_std) -#include "main.moc" -- cgit v1.2.3 From 780d21e1290cb289ae330c46597a381c61b2d86c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 20 Apr 2016 18:50:12 +0200 Subject: fix example installs Change-Id: Ib34795f10b1d7120b28958127ced049af3b4f72b Reviewed-by: Joerg Bornemann --- examples/corelib/tools/customtype/customtype.pro | 2 +- examples/corelib/tools/customtypesending/customtypesending.pro | 2 +- examples/opengl/contextinfo/contextinfo.pro | 4 ++++ examples/widgets/itemviews/storageview/storageview.pro | 4 ++++ examples/widgets/tools/echoplugin/echoplugin.pro | 4 ---- examples/widgets/tools/echoplugin/echowindow/echowindow.pro | 2 ++ examples/widgets/tools/echoplugin/plugin/plugin.pro | 4 +++- examples/widgets/tools/plugandpaint/app/app.pro | 2 ++ examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro | 2 ++ .../widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro | 2 ++ examples/widgets/tools/styleplugin/plugin/plugin.pro | 2 ++ examples/widgets/tools/styleplugin/styleplugin.pro | 4 ---- examples/widgets/tools/styleplugin/stylewindow/stylewindow.pro | 2 ++ 13 files changed, 25 insertions(+), 11 deletions(-) diff --git a/examples/corelib/tools/customtype/customtype.pro b/examples/corelib/tools/customtype/customtype.pro index 1bd792db85..0e0fe9b1a5 100644 --- a/examples/corelib/tools/customtype/customtype.pro +++ b/examples/corelib/tools/customtype/customtype.pro @@ -4,5 +4,5 @@ SOURCES = main.cpp \ QT += widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customcompleter +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customtype INSTALLS += target diff --git a/examples/corelib/tools/customtypesending/customtypesending.pro b/examples/corelib/tools/customtypesending/customtypesending.pro index 672f6569c2..da351ce828 100644 --- a/examples/corelib/tools/customtypesending/customtypesending.pro +++ b/examples/corelib/tools/customtypesending/customtypesending.pro @@ -6,5 +6,5 @@ SOURCES = main.cpp \ QT += widgets # install -target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customcompleter +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/tools/customtypesending INSTALLS += target diff --git a/examples/opengl/contextinfo/contextinfo.pro b/examples/opengl/contextinfo/contextinfo.pro index ddaa084f38..2836e5ea5a 100644 --- a/examples/opengl/contextinfo/contextinfo.pro +++ b/examples/opengl/contextinfo/contextinfo.pro @@ -7,3 +7,7 @@ SOURCES += main.cpp \ HEADERS += widget.h \ renderwindow.h + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/opengl/contextinfo +INSTALLS += target diff --git a/examples/widgets/itemviews/storageview/storageview.pro b/examples/widgets/itemviews/storageview/storageview.pro index c5c01dc4f1..07e7fb5145 100644 --- a/examples/widgets/itemviews/storageview/storageview.pro +++ b/examples/widgets/itemviews/storageview/storageview.pro @@ -5,3 +5,7 @@ SOURCES += storagemodel.cpp \ main.cpp HEADERS += \ storagemodel.h + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/storageview +INSTALLS += target diff --git a/examples/widgets/tools/echoplugin/echoplugin.pro b/examples/widgets/tools/echoplugin/echoplugin.pro index d95eb6b64a..1e3d625b2f 100644 --- a/examples/widgets/tools/echoplugin/echoplugin.pro +++ b/examples/widgets/tools/echoplugin/echoplugin.pro @@ -3,7 +3,3 @@ TEMPLATE = subdirs SUBDIRS = echowindow \ plugin #! [0] - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/echoplugin -INSTALLS += target diff --git a/examples/widgets/tools/echoplugin/echowindow/echowindow.pro b/examples/widgets/tools/echoplugin/echowindow/echowindow.pro index fca0252a82..092258dd30 100644 --- a/examples/widgets/tools/echoplugin/echowindow/echowindow.pro +++ b/examples/widgets/tools/echoplugin/echowindow/echowindow.pro @@ -17,3 +17,5 @@ win32 { # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/echoplugin INSTALLS += target + +CONFIG += install_ok # Do not cargo-cult this! diff --git a/examples/widgets/tools/echoplugin/plugin/plugin.pro b/examples/widgets/tools/echoplugin/plugin/plugin.pro index 4afe56c024..a4b54b18f6 100644 --- a/examples/widgets/tools/echoplugin/plugin/plugin.pro +++ b/examples/widgets/tools/echoplugin/plugin/plugin.pro @@ -12,5 +12,7 @@ DESTDIR = ../plugins EXAMPLE_FILES = echoplugin.json # install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/echoplugin/plugin +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/echoplugin/plugins INSTALLS += target + +CONFIG += install_ok # Do not cargo-cult this! diff --git a/examples/widgets/tools/plugandpaint/app/app.pro b/examples/widgets/tools/plugandpaint/app/app.pro index 45fb7224e0..8139cd53ad 100644 --- a/examples/widgets/tools/plugandpaint/app/app.pro +++ b/examples/widgets/tools/plugandpaint/app/app.pro @@ -24,3 +24,5 @@ if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint INSTALLS += target + +CONFIG += install_ok # Do not cargo-cult this! diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro index 0c0a262339..f28be96b03 100644 --- a/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro +++ b/examples/widgets/tools/plugandpaint/plugins/basictools/basictools.pro @@ -12,3 +12,5 @@ DESTDIR = ../../plugins # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins INSTALLS += target + +CONFIG += install_ok # Do not cargo-cult this! diff --git a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro index 0c86a575f3..deb3c5e70e 100644 --- a/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro +++ b/examples/widgets/tools/plugandpaint/plugins/extrafilters/extrafilters.pro @@ -12,3 +12,5 @@ DESTDIR = ../../plugins # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/plugandpaint/plugins INSTALLS += target + +CONFIG += install_ok # Do not cargo-cult this! diff --git a/examples/widgets/tools/styleplugin/plugin/plugin.pro b/examples/widgets/tools/styleplugin/plugin/plugin.pro index c7e8de6ee2..35184fc82a 100644 --- a/examples/widgets/tools/styleplugin/plugin/plugin.pro +++ b/examples/widgets/tools/styleplugin/plugin/plugin.pro @@ -20,3 +20,5 @@ EXAMPLE_FILES += simplestyle.json # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/styleplugin/styles INSTALLS += target + +CONFIG += install_ok # Do not cargo-cult this! diff --git a/examples/widgets/tools/styleplugin/styleplugin.pro b/examples/widgets/tools/styleplugin/styleplugin.pro index b9f251116d..4f120637b0 100644 --- a/examples/widgets/tools/styleplugin/styleplugin.pro +++ b/examples/widgets/tools/styleplugin/styleplugin.pro @@ -1,7 +1,3 @@ TEMPLATE = subdirs SUBDIRS = stylewindow \ plugin - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/styleplugin -INSTALLS += target diff --git a/examples/widgets/tools/styleplugin/stylewindow/stylewindow.pro b/examples/widgets/tools/styleplugin/stylewindow/stylewindow.pro index 56aa373b0e..cdc1bd2fda 100644 --- a/examples/widgets/tools/styleplugin/stylewindow/stylewindow.pro +++ b/examples/widgets/tools/styleplugin/stylewindow/stylewindow.pro @@ -15,3 +15,5 @@ win32 { # install target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/styleplugin INSTALLS += target + +CONFIG += install_ok # Do not cargo-cult this! -- cgit v1.2.3 From 155533e05995c743f8ba983055f7df98d0960c48 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 3 May 2016 11:28:34 +0200 Subject: Fix grammar in QSKIP documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia57dd2c859ae5b025515c45593a7f89a1b7f28ff Reviewed-by: Topi Reiniö --- src/testlib/qtestcase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 6e30a5d429..62649441db 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -420,7 +420,7 @@ static void stackTrace() row of test data, so an unconditional call to QSKIP will produce one skip message in the test log for each row of test data. - If called from an _data function, the QSKIP() macro will stop execution of + If called from a _data function, the QSKIP() macro will stop execution of the _data function and will prevent execution of the associated test function. -- cgit v1.2.3 From 73df18e16108fdfc3d9e4c60bbfc328d769d4234 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Tue, 9 Feb 2016 10:48:26 +0100 Subject: Added a missing comma to the comment. Change-Id: Ia32c9b298dc35ccdd95d92550c06cff52f918ea1 Reviewed-by: Nico Vertriest --- src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp index 9252aa1cad..930a11d7a1 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp @@ -160,7 +160,7 @@ QImage scaledToWith(const QImage &image) //! [13] QList images = ...; -QFuture thumbnails = QtConcurrent::mapped(images, std::bind(&QImage::scaledToWidth, 100 Qt::SmoothTransformation)); +QFuture thumbnails = QtConcurrent::mapped(images, std::bind(&QImage::scaledToWidth, 100, Qt::SmoothTransformation)); //! [13] //! [14] -- cgit v1.2.3 From e6b1e918e12df25a359fbb87ae26f584d46df823 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 2 May 2016 11:02:09 +0200 Subject: QLinuxFbScreen: fix uninitialized member warnings Prompted by Coverity CID 11720 (allegedly recently new in dev but long-standing in 5.6). Even assuming the class is used correctly - test initialize() and only use if that succeeded - the destructor would have passed uninitialized arguments to munmap() and ioctl(). Noticed a double close along the way: it's been fixed on dev but should have been fixed in 5.6, too. Documented why ioctl() failure in switchToGraphicsMode() should at least do no harm. Change-Id: Ie26a9eefa435b5ff5b1a02e03e29469b8db72d3c Reviewed-by: Laszlo Agocs --- src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp | 30 ++++++++++-------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index 91708c0a47..8c3e73fd80 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -256,15 +256,15 @@ static int openTtyDevice(const QString &device) return fd; } -static bool switchToGraphicsMode(int ttyfd, int *oldMode) +static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode) { - ioctl(ttyfd, KDGETMODE, oldMode); - if (*oldMode != KD_GRAPHICS) { - if (ioctl(ttyfd, KDSETMODE, KD_GRAPHICS) != 0) - return false; + // Do not warn if the switch fails: the ioctl fails when launching from a + // remote console and there is nothing we can do about it. The matching + // call in resetTty should at least fail then, too, so we do no harm. + if (ioctl(ttyfd, KDGETMODE, oldMode) == 0) { + if (doSwitch && *oldMode != KD_GRAPHICS) + ioctl(ttyfd, KDSETMODE, KD_GRAPHICS); } - - return true; } static void resetTty(int ttyfd, int oldMode) @@ -280,21 +280,21 @@ static void blankScreen(int fd, bool on) } QLinuxFbScreen::QLinuxFbScreen(const QStringList &args) - : mArgs(args), mFbFd(-1), mBlitter(0) + : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0) { + mMmap.data = 0; } QLinuxFbScreen::~QLinuxFbScreen() { if (mFbFd != -1) { - munmap(mMmap.data - mMmap.offset, mMmap.size); + if (mMmap.data) + munmap(mMmap.data - mMmap.offset, mMmap.size); close(mFbFd); } - if (mTtyFd != -1) { + if (mTtyFd != -1) resetTty(mTtyFd, mOldTtyMode); - close(mTtyFd); - } delete mBlitter; } @@ -389,11 +389,7 @@ bool QLinuxFbScreen::initialize() if (mTtyFd == -1) qErrnoWarning(errno, "Failed to open tty"); - if (doSwitchToGraphicsMode) - switchToGraphicsMode(mTtyFd, &mOldTtyMode); - // Do not warn if the switch fails: the ioctl fails when launching from - // a remote console and there is nothing we can do about it. - + switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode); blankScreen(mFbFd, false); return true; -- cgit v1.2.3 From ecf127505effbbf4dbfd1e7cb9561de5dae51bf2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 22 Apr 2016 17:13:38 +0200 Subject: egl: Reshuffle headers to help less fortunate systems with X11 EGL headers including X headers has traditionally been problematic due to getting macros for Status, None, etc. In most cases this is not an issue anymore because on embedded one will almost always use a driver targeting the framebuffer or DRM/KMS and therefore the EGL headers do not pull in X dependencies. Furthermore, Mesa supports MESA_EGL_NO_X11_HEADERS which we set, avoiding the problem altogether with Mesa regardless of targeting X11 or KMS. However, other drivers do not have this option. On i.MX6 for instance, targeting X11 is problematic due to not having EGL_API_FB defined, which in turn means the EGL headers pulls in X headers in order to be able to define the native display and window types as Display and Window. Try to play nice with this use case by reshuffling the includes and undefining the problematic names. Task-number: QTBUG-52928 Change-Id: I059f26b340b6e442e7296055915d18f5a1ce7a7f Reviewed-by: Louai Al-Khanji --- .../eglconvenience/eglconvenience.pri | 3 +- .../eglconvenience/qeglconvenience_p.h | 2 +- src/platformsupport/eglconvenience/qeglpbuffer_p.h | 2 +- .../eglconvenience/qeglplatformcontext_p.h | 2 +- .../eglconvenience/qeglstreamconvenience_p.h | 3 +- src/platformsupport/eglconvenience/qt_egl_p.h | 67 ++++++++++++++++++++++ src/plugins/platforms/eglfs/qeglfscontext.cpp | 1 + src/plugins/platforms/eglfs/qeglfscontext.h | 2 +- .../platforms/eglfs/qeglfsdeviceintegration.h | 3 +- src/plugins/platforms/eglfs/qeglfsglobal.h | 1 + src/plugins/platforms/eglfs/qeglfshooks.h | 2 +- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 2 - src/plugins/platforms/eglfs/qeglfsintegration.h | 3 +- .../platforms/eglfs/qeglfsoffscreenwindow.h | 3 +- src/plugins/platforms/eglfs/qeglfsscreen.h | 1 - src/plugins/platforms/eglfs/qeglfswindow.h | 3 +- .../xcb/gl_integrations/xcb_egl/qxcbeglinclude.h | 2 +- src/plugins/platforms/xcb/qxcbintegration.cpp | 2 +- 18 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 src/platformsupport/eglconvenience/qt_egl_p.h diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index f1e0d58a6d..7ad0209e99 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -1,7 +1,8 @@ contains(QT_CONFIG,egl) { HEADERS += \ $$PWD/qeglconvenience_p.h \ - $$PWD/qeglstreamconvenience_p.h + $$PWD/qeglstreamconvenience_p.h \ + $$PWD/qt_egl_p.h SOURCES += \ $$PWD/qeglconvenience.cpp \ diff --git a/src/platformsupport/eglconvenience/qeglconvenience_p.h b/src/platformsupport/eglconvenience/qeglconvenience_p.h index ec6f668cba..027930d2c2 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglconvenience_p.h @@ -48,7 +48,7 @@ #include #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h index 81fdab8901..a932762a67 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer_p.h +++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h @@ -45,9 +45,9 @@ // We mean it. // -#include #include #include +#include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 41601272a3..666c5fa0f3 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -49,7 +49,7 @@ #include #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h index 648b129579..ac81c2ff0e 100644 --- a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h @@ -46,8 +46,7 @@ // #include -#include -#include +#include // This provides runtime EGLDevice/Output/Stream support even when eglext.h in // the sysroot is not up-to-date. diff --git a/src/platformsupport/eglconvenience/qt_egl_p.h b/src/platformsupport/eglconvenience/qt_egl_p.h new file mode 100644 index 0000000000..d03ac02588 --- /dev/null +++ b/src/platformsupport/eglconvenience/qt_egl_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT_EGL_P_H +#define QT_EGL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#undef Status +#undef None +#undef Bool +#undef CursorShape +#undef KeyPress +#undef KeyRelease +#undef FocusIn +#undef FocusOut +#undef FontChange +#undef Expose +#undef Unsorted + +QT_BEGIN_NAMESPACE + +QT_END_NAMESPACE + +#endif // QT_EGL_P_H diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index db35338423..bb638091f7 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -31,6 +31,7 @@ ** ****************************************************************************/ +#include "qeglfsglobal.h" #include #include #include diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h index 906d11b3d1..8da4c731b8 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -34,9 +34,9 @@ #ifndef QEGLFSCONTEXT_H #define QEGLFSCONTEXT_H +#include "qeglfsglobal.h" #include #include -#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h index 5ec98b37d1..303810eb6e 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h @@ -45,13 +45,12 @@ // We mean it. // +#include "qeglfsglobal.h" #include #include #include #include #include -#include -#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsglobal.h b/src/plugins/platforms/eglfs/qeglfsglobal.h index 9109f6be38..bd6e208266 100644 --- a/src/plugins/platforms/eglfs/qeglfsglobal.h +++ b/src/plugins/platforms/eglfs/qeglfsglobal.h @@ -35,6 +35,7 @@ #define QEGLFSGLOBAL_H #include +#include #ifdef QT_BUILD_EGL_DEVICE_LIB #define Q_EGLFS_EXPORT Q_DECL_EXPORT diff --git a/src/plugins/platforms/eglfs/qeglfshooks.h b/src/plugins/platforms/eglfs/qeglfshooks.h index 3e4143918e..5f19d492f8 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks.h +++ b/src/plugins/platforms/eglfs/qeglfshooks.h @@ -34,8 +34,8 @@ #ifndef QEGLFSHOOKS_H #define QEGLFSHOOKS_H -#include "qeglfsdeviceintegration.h" #include "qeglfsglobal.h" +#include "qeglfsdeviceintegration.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 35b27cba0b..c226c0134a 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -79,8 +79,6 @@ #include -#include - static void initResources() { #ifndef QT_NO_CURSOR diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index 98c7ee9f78..2edb287b1e 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -34,12 +34,11 @@ #ifndef QEGLFSINTEGRATION_H #define QEGLFSINTEGRATION_H +#include "qeglfsglobal.h" #include #include #include #include -#include -#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h index 9b8eaacd51..f20055b4e7 100644 --- a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h @@ -34,9 +34,8 @@ #ifndef QEGLFSOFFSCREENWINDOW_H #define QEGLFSOFFSCREENWINDOW_H -#include -#include #include "qeglfsglobal.h" +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h index 8f1d87ea25..ea669bd5bc 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -36,7 +36,6 @@ #include "qeglfsglobal.h" #include -#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 806b21de0a..2c396e8ef4 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -34,13 +34,12 @@ #ifndef QEGLFSWINDOW_H #define QEGLFSWINDOW_H +#include "qeglfsglobal.h" #include "qeglfsintegration.h" #include "qeglfsscreen.h" -#include "qeglfsglobal.h" #include #include -#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h index ec59cbc7c9..ce655462e4 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h @@ -40,7 +40,7 @@ #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 94e17a2983..1176ee10c9 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -59,7 +59,7 @@ #include #ifdef XCB_USE_EGL -#include +#include #endif #ifdef XCB_USE_XLIB -- cgit v1.2.3 From 2422c1a22720e99f63f7d0f132a0ba7b02da5039 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 14 Apr 2016 16:20:06 -0700 Subject: Cocoa: Enable skipping Ctrl+LMB to RMB override This can be enabled with QT_MAC_DONT_OVERRIDE_CTRL_LMB=1 environment variable. The goal is to provide consistent cross-platform input when it's more desirable than full platform comformance. Change-Id: I3b96733077bd1c0367edeef21a98a44b15425807 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qnsview.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a2f97c78dc..4b7b50a265 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -70,6 +70,8 @@ static QTouchDevice *touchDevice = 0; // ### HACK Remove once 10.8 is unsupported static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; +static bool _q_dontOverrideCtrlLMB = false; + @interface NSEvent (Qt_Compile_Leopard_DeviceDelta) - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; @@ -130,6 +132,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; NSString **notificationNameVar = (NSString **)dlsym(RTLD_NEXT, "NSWindowDidChangeOcclusionStateNotification"); if (notificationNameVar) _q_NSWindowDidChangeOcclusionStateNotification = *notificationNameVar; + + _q_dontOverrideCtrlLMB = qt_mac_resolveOption(false, "QT_MAC_DONT_OVERRIDE_CTRL_LMB"); } - (id) init @@ -854,7 +858,7 @@ QT_WARNING_POP if ([self hasMarkedText]) { [[NSTextInputContext currentInputContext] handleEvent:theEvent]; } else { - if ([QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { + if (!_q_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { m_buttons |= Qt::RightButton; m_sendUpAsRightButton = true; } else { -- cgit v1.2.3 From 60cd1c67759642018ef93cc45a90714729100d9d Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 28 Apr 2016 11:30:30 +0200 Subject: xcb: don't compress tablet motion events 7edd10e6c added this compression feature, but it's not a good idea for drawing-tablet applications, because smooth drawing depends on receiving every movement of the stylus. Also show the device ID in qt.qpa.input.devices category logging. [ChangeLog][X11] The new X event compression feature that was added in 5.6.0 no longer applies to motion events from drawing tablets. Task-number: QTBUG-44964 Change-Id: Icd2ca8ca77d8f80c2f39160c74208db10e382501 Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbconnection.cpp | 7 ++++++- src/plugins/platforms/xcb/qxcbconnection.h | 1 + src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 21 ++++++++++++++------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index edfaf2b015..669ef3a98e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1626,8 +1626,13 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, if (!m_xi2Enabled) return false; - // compress XI_Motion + // compress XI_Motion, but not from tablet devices if (isXIType(event, m_xiOpCode, XI_Motion)) { +#ifndef QT_NO_TABLETEVENT + xXIDeviceEvent *xdev = reinterpret_cast(event); + if (const_cast(this)->tabletDataForDevice(xdev->sourceid)) + return false; +#endif // QT_NO_TABLETEVENT for (int j = nextIndex; j < eventqueue->size(); ++j) { xcb_generic_event_t *next = eventqueue->at(j); if (!isValid(next)) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7ba95887ff..501da1ce7b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -578,6 +578,7 @@ private: bool xi2HandleTabletEvent(void *event, TabletData *tabletData, QXcbWindowEventListener *eventListener); void xi2ReportTabletEvent(TabletData &tabletData, void *event); QVector m_tabletData; + TabletData *tabletDataForDevice(int id); #endif // !QT_NO_TABLETEVENT struct ScrollingDevice { ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0), legacyOrientations(0) { } diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 9911afb11e..025dde3dbb 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -113,7 +113,7 @@ void QXcbConnection::xi2SetupDevices() // Only non-master pointing devices are relevant here. if (devices[i].use != XISlavePointer) continue; - qCDebug(lcQpaXInputDevices) << "input device "<< devices[i].name; + qCDebug(lcQpaXInputDevices) << "input device " << devices[i].name << "ID" << devices[i].deviceid; #ifndef QT_NO_TABLETEVENT TabletData tabletData; #endif @@ -530,12 +530,9 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) #ifndef QT_NO_TABLETEVENT if (!xiEnterEvent) { - for (int i = 0; i < m_tabletData.count(); ++i) { - if (m_tabletData.at(i).deviceId == sourceDeviceId) { - if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener)) - return; - } - } + QXcbConnection::TabletData *tablet = tabletDataForDevice(sourceDeviceId); + if (tablet && xi2HandleTabletEvent(xiEvent, tablet, eventListener)) + return; } #endif // QT_NO_TABLETEVENT @@ -1198,6 +1195,16 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event) xTilt, yTilt, tangentialPressure, rotation, 0, tabletData.serialId); } + +QXcbConnection::TabletData *QXcbConnection::tabletDataForDevice(int id) +{ + for (int i = 0; i < m_tabletData.count(); ++i) { + if (m_tabletData.at(i).deviceId == id) + return &m_tabletData[i]; + } + return Q_NULLPTR; +} + #endif // QT_NO_TABLETEVENT #endif // XCB_USE_XINPUT2 -- cgit v1.2.3 From 63ec10353db7aaaf227f769398056b6fd42f9b7d Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Wed, 4 May 2016 10:44:53 +0200 Subject: Revert "egl: Reshuffle headers to help less fortunate systems with X11" This reverts commit ecf127505effbbf4dbfd1e7cb9561de5dae51bf2. ecf12750 breaks the build of qtwayland. Change-Id: If8bf04f035aa47e4e867d201ec7d95b0d3e18317 Reviewed-by: Laszlo Agocs --- .../eglconvenience/eglconvenience.pri | 3 +- .../eglconvenience/qeglconvenience_p.h | 2 +- src/platformsupport/eglconvenience/qeglpbuffer_p.h | 2 +- .../eglconvenience/qeglplatformcontext_p.h | 2 +- .../eglconvenience/qeglstreamconvenience_p.h | 3 +- src/platformsupport/eglconvenience/qt_egl_p.h | 67 ---------------------- src/plugins/platforms/eglfs/qeglfscontext.cpp | 1 - src/plugins/platforms/eglfs/qeglfscontext.h | 2 +- .../platforms/eglfs/qeglfsdeviceintegration.h | 3 +- src/plugins/platforms/eglfs/qeglfsglobal.h | 1 - src/plugins/platforms/eglfs/qeglfshooks.h | 2 +- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 2 + src/plugins/platforms/eglfs/qeglfsintegration.h | 3 +- .../platforms/eglfs/qeglfsoffscreenwindow.h | 3 +- src/plugins/platforms/eglfs/qeglfsscreen.h | 1 + src/plugins/platforms/eglfs/qeglfswindow.h | 3 +- .../xcb/gl_integrations/xcb_egl/qxcbeglinclude.h | 2 +- src/plugins/platforms/xcb/qxcbintegration.cpp | 2 +- 18 files changed, 21 insertions(+), 83 deletions(-) delete mode 100644 src/platformsupport/eglconvenience/qt_egl_p.h diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index 7ad0209e99..f1e0d58a6d 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -1,8 +1,7 @@ contains(QT_CONFIG,egl) { HEADERS += \ $$PWD/qeglconvenience_p.h \ - $$PWD/qeglstreamconvenience_p.h \ - $$PWD/qt_egl_p.h + $$PWD/qeglstreamconvenience_p.h SOURCES += \ $$PWD/qeglconvenience.cpp \ diff --git a/src/platformsupport/eglconvenience/qeglconvenience_p.h b/src/platformsupport/eglconvenience/qeglconvenience_p.h index 027930d2c2..ec6f668cba 100644 --- a/src/platformsupport/eglconvenience/qeglconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglconvenience_p.h @@ -48,7 +48,7 @@ #include #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h index a932762a67..81fdab8901 100644 --- a/src/platformsupport/eglconvenience/qeglpbuffer_p.h +++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h @@ -45,9 +45,9 @@ // We mean it. // +#include #include #include -#include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h index 666c5fa0f3..41601272a3 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h @@ -49,7 +49,7 @@ #include #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h index ac81c2ff0e..648b129579 100644 --- a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h @@ -46,7 +46,8 @@ // #include -#include +#include +#include // This provides runtime EGLDevice/Output/Stream support even when eglext.h in // the sysroot is not up-to-date. diff --git a/src/platformsupport/eglconvenience/qt_egl_p.h b/src/platformsupport/eglconvenience/qt_egl_p.h deleted file mode 100644 index d03ac02588..0000000000 --- a/src/platformsupport/eglconvenience/qt_egl_p.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT_EGL_P_H -#define QT_EGL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -#undef Status -#undef None -#undef Bool -#undef CursorShape -#undef KeyPress -#undef KeyRelease -#undef FocusIn -#undef FocusOut -#undef FontChange -#undef Expose -#undef Unsorted - -QT_BEGIN_NAMESPACE - -QT_END_NAMESPACE - -#endif // QT_EGL_P_H diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index bb638091f7..db35338423 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -31,7 +31,6 @@ ** ****************************************************************************/ -#include "qeglfsglobal.h" #include #include #include diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h index 8da4c731b8..906d11b3d1 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -34,9 +34,9 @@ #ifndef QEGLFSCONTEXT_H #define QEGLFSCONTEXT_H -#include "qeglfsglobal.h" #include #include +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h index 303810eb6e..5ec98b37d1 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h @@ -45,12 +45,13 @@ // We mean it. // -#include "qeglfsglobal.h" #include #include #include #include #include +#include +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsglobal.h b/src/plugins/platforms/eglfs/qeglfsglobal.h index bd6e208266..9109f6be38 100644 --- a/src/plugins/platforms/eglfs/qeglfsglobal.h +++ b/src/plugins/platforms/eglfs/qeglfsglobal.h @@ -35,7 +35,6 @@ #define QEGLFSGLOBAL_H #include -#include #ifdef QT_BUILD_EGL_DEVICE_LIB #define Q_EGLFS_EXPORT Q_DECL_EXPORT diff --git a/src/plugins/platforms/eglfs/qeglfshooks.h b/src/plugins/platforms/eglfs/qeglfshooks.h index 5f19d492f8..3e4143918e 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks.h +++ b/src/plugins/platforms/eglfs/qeglfshooks.h @@ -34,8 +34,8 @@ #ifndef QEGLFSHOOKS_H #define QEGLFSHOOKS_H -#include "qeglfsglobal.h" #include "qeglfsdeviceintegration.h" +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index c226c0134a..35b27cba0b 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -79,6 +79,8 @@ #include +#include + static void initResources() { #ifndef QT_NO_CURSOR diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index 2edb287b1e..98c7ee9f78 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -34,11 +34,12 @@ #ifndef QEGLFSINTEGRATION_H #define QEGLFSINTEGRATION_H -#include "qeglfsglobal.h" #include #include #include #include +#include +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h index f20055b4e7..9b8eaacd51 100644 --- a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h @@ -34,8 +34,9 @@ #ifndef QEGLFSOFFSCREENWINDOW_H #define QEGLFSOFFSCREENWINDOW_H -#include "qeglfsglobal.h" +#include #include +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h index ea669bd5bc..8f1d87ea25 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -36,6 +36,7 @@ #include "qeglfsglobal.h" #include +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 2c396e8ef4..806b21de0a 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -34,12 +34,13 @@ #ifndef QEGLFSWINDOW_H #define QEGLFSWINDOW_H -#include "qeglfsglobal.h" #include "qeglfsintegration.h" #include "qeglfsscreen.h" +#include "qeglfsglobal.h" #include #include +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h index ce655462e4..ec59cbc7c9 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h @@ -40,7 +40,7 @@ #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 1176ee10c9..94e17a2983 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -59,7 +59,7 @@ #include #ifdef XCB_USE_EGL -#include +#include #endif #ifdef XCB_USE_XLIB -- cgit v1.2.3 From 67509693bdac23af4e062140a1b1058dee3f060b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Mon, 14 Dec 2015 10:42:51 +0100 Subject: Improve tst_qtimeline::setPaused resilience MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test should not depend on qWait explicitly Change-Id: I13c01c47c9f7bae8b0c30afa2ac8550dc0fbf028 Reviewed-by: Friedemann Kleint Reviewed-by: Jan Arve Sæther --- tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp b/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp index b588e1fe82..dd41b5632d 100644 --- a/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp +++ b/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp @@ -649,22 +649,21 @@ void tst_QTimeLine::restart() void tst_QTimeLine::setPaused() { - QTimeLine timeLine(1000); + const int EndTime = 10000; + QTimeLine timeLine(EndTime); { QCOMPARE(timeLine.currentTime(), 0); timeLine.start(); - QTest::qWait(250); + QTRY_VERIFY(timeLine.currentTime() != 0); // wait for start timeLine.setPaused(true); int oldCurrentTime = timeLine.currentTime(); QVERIFY(oldCurrentTime > 0); - QVERIFY(oldCurrentTime < 1000); + QVERIFY(oldCurrentTime < EndTime); QTest::qWait(1000); timeLine.setPaused(false); - QTest::qWait(250); - int currentTime = timeLine.currentTime(); - QVERIFY(currentTime > 0); - QVERIFY(currentTime > oldCurrentTime); - QVERIFY(currentTime < 1000); + QTRY_VERIFY(timeLine.currentTime() > oldCurrentTime); + QVERIFY(timeLine.currentTime() > 0); + QVERIFY(timeLine.currentTime() < EndTime); timeLine.stop(); } } -- cgit v1.2.3 From 54781edbaabc563f1fb6e4f14edc35e675009ac7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 4 May 2016 09:32:30 +0200 Subject: Manual touch test: Add color for Qt::MouseEventSynthesizedByApplication. Fix a warning about a missing case statement. Change-Id: Ic89646704d62668cf83c463dbf6e9b549a4b5200 Reviewed-by: Shawn Rutledge --- tests/manual/touch/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/manual/touch/main.cpp b/tests/manual/touch/main.cpp index 2a5c2b508e..6fa8141361 100644 --- a/tests/manual/touch/main.cpp +++ b/tests/manual/touch/main.cpp @@ -261,6 +261,9 @@ QColor Point::color() const case Qt::MouseEventSynthesizedByQt: globalColor = Qt::blue; break; + case Qt::MouseEventSynthesizedByApplication: + globalColor = Qt::green; + break; case Qt::MouseEventNotSynthesized: break; } -- cgit v1.2.3 From b75e10684cb4d14e49059e6c85bfe60ca6ab9dff Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 4 May 2016 09:57:46 +0200 Subject: doc: Clarify how to remove a QTextFrame The documentation wrongfully recommended deleting QTextFrames directly. This would cause a crash, since the destructor didn't update the document's layout at all. The correct way is the same as when removing other aspects of the document. Task-number: QTBUG-53082 Change-Id: I64f0ad08f1d063626456fa51d03611871ce6aa45 Reviewed-by: Simon Hausmann --- src/gui/text/qtextobject.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index e70b8ed300..e1cfd22295 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -412,9 +412,12 @@ QTextFrame::QTextFrame(QTextDocument *doc) { } -// ### DOC: What does this do to child frames? /*! - Destroys the frame, and removes it from the document's layout. + Destroys the text frame. + + \warning Text frames are owned by the document, so you should + never destroy them yourself. In order to remove a frame from + its document, remove its contents using a \c QTextCursor. */ QTextFrame::~QTextFrame() { -- cgit v1.2.3 From b3e9144c3a326af26d94e0cbd448357d3072a650 Mon Sep 17 00:00:00 2001 From: Elena Zaretskaya Date: Sat, 9 Apr 2016 00:46:24 +0400 Subject: Fix FPE under EGLFS_KMS if mesa-10.2.7 If mesa-10.2.7 is installed, gbm_bo_create returns NULL (QEglFSKmsCursor ctor, qeglfskmscursor.cpp:80), but after that the pointer m_bo is used in function QEGlFSKmsCursor::changeCursor without verification. Task-number: QTBUG-52404 Change-Id: I5b1b15d751e46a5200248e7a8642f7917dedd220 Reviewed-by: Laszlo Agocs --- .../eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp index dda61e3901..97ea3f1eca 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp @@ -100,8 +100,10 @@ QEglFSKmsCursor::~QEglFSKmsCursor() drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); } - gbm_bo_destroy(m_bo); - m_bo = Q_NULLPTR; + if (m_bo) { + gbm_bo_destroy(m_bo); + m_bo = Q_NULLPTR; + } } void QEglFSKmsCursor::pointerEvent(const QMouseEvent &event) @@ -114,6 +116,9 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window) { Q_UNUSED(window); + if (!m_bo) + return; + if (!m_visible) return; -- cgit v1.2.3 From 8d45759432e7f954360b76ddeaf2b09acee8606e Mon Sep 17 00:00:00 2001 From: Elena Zaretskaya Date: Fri, 8 Apr 2016 12:29:25 +0400 Subject: Fix segfault when exiting app running under eglfs In function QWindow::destroy() the platformWindow is destroyed (QEglFSWindow in this case), but after that the QSurface destructor is called (qsurface.cpp:127), where access to the opengl context is performed (QOpenGLContext::currentContext()->doneCurrent()). Therefore the surface pointer is deleted earlier (gbm_surface_destroy) than the working with it (eglMakeCurrent) is finished. But the event QPlatformSurfaceEvent, that is sent before deleting platformWindow, isn't processed (qwindow.cpp:1665), though we can perform doneCurrent() in the handler of QPlatformSurfaceEvent. The full description with valgrind stacks on bugreports. Task-number: QTBUG-52399 Change-Id: I69035dfd8ba5b5eeec243bc0edd3f571dc9525f9 Reviewed-by: Laszlo Agocs --- src/gui/kernel/qwindow.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 68bcbdec71..7f84706b6f 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2109,6 +2109,17 @@ bool QWindow::event(QEvent *ev) break; } + case QEvent::PlatformSurface: { + if ((static_cast(ev))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) { +#ifndef QT_NO_OPENGL + QOpenGLContext *context = QOpenGLContext::currentContext(); + if (context && context->surface() == static_cast(this)) + context->doneCurrent(); +#endif + } + break; + } + default: return QObject::event(ev); } -- cgit v1.2.3 From 2c60125ef967d157b8c1de8eec7e40dcef424c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 4 May 2016 12:07:20 +0200 Subject: Add missing Q_DECL_OVERRIDEs Change-Id: I54552d9fdd0bc8871247246aea1da14848c4f7a0 Reviewed-by: Timur Pocheptsov --- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 55b6aff237..92e504e1fb 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -5862,7 +5862,7 @@ public: startTimer(1000); } - void timerEvent(QTimerEvent *) + void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE { switch (state++) { case 0: @@ -5885,7 +5885,7 @@ public: return false; } - bool nativeEvent(const QByteArray &eventType, void *message, long *) + bool nativeEvent(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE { if (isMapNotify(eventType, message)) gotExpectedMapNotify = true; @@ -5893,7 +5893,7 @@ public: } // QAbstractNativeEventFilter interface - virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE + bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE { if (isMapNotify(eventType, message)) gotExpectedGlobalEvent = true; -- cgit v1.2.3 From dec0b15685985d5b7c56748c0e52cfbdb4d1d6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 4 May 2016 13:01:00 +0200 Subject: Change Q_OS_MAC -> Q_OS_OSX Q_OS_DARWIN is the general replacement for Q_OS_MAC, but most/all of the MAC sections in this test are OS X specific. Change-Id: Ic54af9d3dce1e1952a57e15b74acdedf2af60c79 Reviewed-by: Timur Pocheptsov --- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 56 +++++++++++------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 92e504e1fb..c2b01ea087 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -74,7 +74,7 @@ #include "../../../qtest-config.h" -#if defined(Q_OS_MAC) +#if defined(Q_OS_OSX) #include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile. #endif @@ -141,7 +141,7 @@ bool qt_wince_is_smartphone() { } #endif -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX #include bool macHasAccessToWindowsServer() { @@ -268,7 +268,7 @@ private slots: void restoreVersion1Geometry(); void widgetAt(); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX void sheetOpacity(); void setMask(); #endif @@ -301,7 +301,7 @@ private slots: void update(); void isOpaque(); -#ifndef Q_OS_MAC +#ifndef Q_OS_OSX void scroll(); void scrollNativeChildren(); #endif @@ -434,7 +434,7 @@ private slots: void taskQTBUG_7532_tabOrderWithFocusProxy(); void movedAndResizedAttributes(); void childAt(); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX void childAt_unifiedToolBar(); void taskQTBUG_11373(); #endif @@ -2380,12 +2380,12 @@ void tst_QWidget::showMinimizedKeepsFocus() window.showNormal(); qApp->setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX if (!macHasAccessToWindowsServer()) QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue); #endif QTRY_COMPARE(window.focusWidget(), firstchild); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX if (!macHasAccessToWindowsServer()) QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue); #endif @@ -2725,7 +2725,7 @@ public: void tst_QWidget::lostUpdatesOnHide() { -#ifndef Q_OS_MAC +#ifndef Q_OS_OSX UpdateWidget widget; widget.setAttribute(Qt::WA_DontShowOnScreen); widget.show(); @@ -2767,7 +2767,7 @@ void tst_QWidget::raise() QVERIFY(QTest::qWaitForWindowExposed(parentPtr.data())); QTest::qWait(10); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX if (child1->internalWinId()) { QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events."); } @@ -2947,7 +2947,7 @@ void tst_QWidget::stackUnder() foreach (UpdateWidget *child, allChildren) { int expectedPaintEvents = child == child4 ? 1 : 0; -#if defined(Q_OS_WIN) || defined(Q_OS_MAC) +#if defined(Q_OS_WIN) || defined(Q_OS_OSX) if (expectedPaintEvents == 1 && child->numPaintEvents == 2) QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue); #endif @@ -2986,7 +2986,7 @@ void tst_QWidget::stackUnder() #ifdef Q_OS_WINCE qApp->processEvents(); #endif -#ifndef Q_OS_MAC +#ifndef Q_OS_OSX QEXPECT_FAIL(0, "See QTBUG-493", Continue); #endif QCOMPARE(child->numPaintEvents, 0); @@ -3523,7 +3523,7 @@ void tst_QWidget::testDeletionInEventHandlers() delete w; } -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX void tst_QWidget::sheetOpacity() { QWidget tmpWindow; @@ -4314,7 +4314,7 @@ void tst_QWidget::update() QCOMPARE(sibling.numPaintEvents, 1); QCOMPARE(sibling.paintedRegion, sibling.visibleRegion()); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX if (child.internalWinId()) // child is native QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue); #endif @@ -4340,7 +4340,7 @@ static inline bool isOpaque(QWidget *widget) void tst_QWidget::isOpaque() { -#ifndef Q_OS_MAC +#ifndef Q_OS_OSX QWidget w; QVERIFY(::isOpaque(&w)); @@ -4412,7 +4412,7 @@ void tst_QWidget::isOpaque() #endif } -#ifndef Q_OS_MAC +#ifndef Q_OS_OSX /* Test that scrolling of a widget invalidates the correct regions */ @@ -4859,7 +4859,7 @@ void tst_QWidget::windowMoveResize() widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); -#if defined(Q_OS_MAC) +#if defined(Q_OS_OSX) if (r.width() == 0 && r.height() > 0) { widget.move(r.topLeft()); widget.resize(r.size()); @@ -4930,7 +4930,7 @@ void tst_QWidget::windowMoveResize() widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); -#if defined(Q_OS_MAC) +#if defined(Q_OS_OSX) if (r.width() == 0 && r.height() > 0) { widget.move(r.topLeft()); widget.resize(r.size()); @@ -5120,7 +5120,7 @@ void tst_QWidget::moveChild() QTRY_COMPARE(pos, child.pos()); QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry()); -#if !defined(Q_OS_MAC) +#if !defined(Q_OS_OSX) // should be scrolled in backingstore QCOMPARE(child.r, QRegion()); #endif @@ -6912,7 +6912,7 @@ void tst_QWidget::render_systemClip() // rrrrrrrrrr // ... -#ifndef Q_OS_MAC +#ifndef Q_OS_OSX for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (i < 50 && j < i) @@ -7916,7 +7916,7 @@ void tst_QWidget::sendUpdateRequestImmediately() void tst_QWidget::doubleRepaint() { -#if defined(Q_OS_MAC) +#if defined(Q_OS_OSX) if (!macHasAccessToWindowsServer()) QSKIP("Not having window server access causes the wrong number of repaints to be issues"); #endif @@ -8626,7 +8626,7 @@ void tst_QWidget::setClearAndResizeMask() QTRY_COMPARE(child.mask(), childMask); QTest::qWait(50); // and ensure that the child widget doesn't get any update. -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QCOMPARE(child.numPaintEvents, 1); @@ -8649,7 +8649,7 @@ void tst_QWidget::setClearAndResizeMask() // and ensure that that the child widget gets an update for the area outside the old mask. QTRY_COMPARE(child.numPaintEvents, 1); outsideOldMask = child.rect(); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (!child.internalWinId()) #endif @@ -8664,7 +8664,7 @@ void tst_QWidget::setClearAndResizeMask() // Mask child widget with a mask that is bigger than the rect child.setMask(QRegion(0, 0, 1000, 1000)); QTest::qWait(100); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_COMPARE(child.numPaintEvents, 1); @@ -8677,7 +8677,7 @@ void tst_QWidget::setClearAndResizeMask() // ...and the same applies when clearing the mask. child.clearMask(); QTest::qWait(100); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_VERIFY(child.numPaintEvents > 0); @@ -8707,7 +8707,7 @@ void tst_QWidget::setClearAndResizeMask() QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask())); QTest::qWait(200); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask()); @@ -8719,7 +8719,7 @@ void tst_QWidget::setClearAndResizeMask() const QRegion oldMask = resizeChild.mask(); QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask())); QTest::qWait(100); -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask()); @@ -9432,7 +9432,7 @@ void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy() void tst_QWidget::movedAndResizedAttributes() { -#if defined (Q_OS_MAC) +#if defined (Q_OS_OSX) QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort); QVERIFY(false); #else @@ -9539,7 +9539,7 @@ void tst_QWidget::childAt() QCOMPARE(parent.childAt(120, 120), grandChild); } -#ifdef Q_OS_MAC +#ifdef Q_OS_OSX void tst_QWidget::childAt_unifiedToolBar() { QLabel *label = new QLabel(QLatin1String("foo")); -- cgit v1.2.3 From 22bcf7ba3433753fd93a59beb9006e6983e1530e Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Tue, 3 May 2016 09:10:32 +0200 Subject: QSplitter: Add note about ownership transfer to addWidget() and insertWidget() Change-Id: I971db2c25e4e667a416f58d148e18c4f11c349f1 Reviewed-by: Marc Mutz --- src/widgets/widgets/qsplitter.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index 20b6a029cd..b6959e2460 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -1093,6 +1093,8 @@ void QSplitter::resizeEvent(QResizeEvent *) If \a widget is already in the splitter, it will be moved to the new position. + \note The splitter takes ownership of the widget. + \sa insertWidget(), widget(), indexOf() */ void QSplitter::addWidget(QWidget *widget) @@ -1107,7 +1109,9 @@ void QSplitter::addWidget(QWidget *widget) If \a widget is already in the splitter, it will be moved to the new position. - if \a index is an invalid index, then the widget will be inserted at the end. + If \a index is an invalid index, then the widget will be inserted at the end. + + \note The splitter takes ownership of the widget. \sa addWidget(), indexOf(), widget() */ -- cgit v1.2.3 From 728a1b4f29f0042fc13299bf6cc78e83cdc9d7f9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 4 May 2016 13:00:42 +0200 Subject: tst_QKeyEvent::modifiers(): Ensure test data row names are pure ASCII. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test used to output random character sequences which contained terminal control characters. Change it to output plain ASCII and Unicode syntax for non-ASCII characters. Change-Id: Ifaa72f50242bd27416a8698a1f5152bc8b902898 Reviewed-by: Jędrzej Nowacki --- tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp index db0bfaf622..811a6d111f 100644 --- a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp +++ b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp @@ -116,6 +116,23 @@ static bool orderByModifier(const QVector &v1, const QVector &v2) return true; } +static QByteArray modifiersTestRowName(const QString &keySequence) +{ + QByteArray result; + QTextStream str(&result); + for (int i = 0, size = keySequence.size(); i < size; ++i) { + const QChar &c = keySequence.at(i); + const ushort uc = c.unicode(); + if (uc > 32 && uc < 128) + str << '"' << c << '"'; + else + str << "U+" << hex << uc << dec; + if (i < size - 1) + str << ','; + } + return result; +} + void tst_QKeyEvent::modifiers_data() { struct Modifier @@ -155,7 +172,8 @@ void tst_QKeyEvent::modifiers_data() mods |= modifier.modifier; } QKeySequence keySequence(keys[0], keys[1], keys[2], keys[3]); - QTest::newRow(keySequence.toString(QKeySequence::NativeText).toUtf8().constData()) << mods; + QTest::newRow(modifiersTestRowName(keySequence.toString(QKeySequence::NativeText)).constData()) + << mods; } } -- cgit v1.2.3 From 4ef269963bad7a76ed03e81b91b94058c812e31b Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Mon, 2 May 2016 12:08:00 +0300 Subject: Avoid use of v4-mapped QHostAddress::AnyIPv4 local address on Windows Some Windows kernels return a v4-mapped QHostAddress::AnyIPv4 as a local address of the socket which bound on both IPv4 and IPv6 interfaces. This address does not match to any special address and should not be used to send the data. To allow handling of the local addresses properly, replace it with QHostAddress::Any. Already tested by tst_qudpsocket. Task-number: QTBUG-52714 Change-Id: Icb7cb75f48cd7ec9b0a9dfaf861ffe0d3093e20d Reviewed-by: Thiago Macieira --- src/network/socket/qnativesocketengine_win.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 770bae7bf3..41834b21ae 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -573,6 +573,19 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() } } + // Some Windows kernels return a v4-mapped QHostAddress::AnyIPv4 as a + // local address of the socket which bound on both IPv4 and IPv6 interfaces. + // This address does not match to any special address and should not be used + // to send the data. So, replace it with QHostAddress::Any. + if (socketProtocol == QAbstractSocket::IPv6Protocol) { + bool ok = false; + const quint32 localIPv4 = localAddress.toIPv4Address(&ok); + if (ok && localIPv4 == INADDR_ANY) { + socketProtocol = QAbstractSocket::AnyIPProtocol; + localAddress = QHostAddress::Any; + } + } + memset(&sa, 0, sizeof(sa)); if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) { qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress); -- cgit v1.2.3 From f57d8f1341587e6b2aa84b8404aa218432584206 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 5 Mar 2016 19:32:02 +0200 Subject: QFileSystemMetaData: do not treat block devices as sequential MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch allows handling of special block devices in random-access mode that restores a Qt4 behavior. Can not be tested because requires root privileges in the system. Task-number: QTBUG-51666 Change-Id: Iaa56355f1be343c0d05b292e3c7d2e1c88724529 Reviewed-by: Edward Welbourne Reviewed-by: Andrius Štikonas Reviewed-by: Oswald Buddenhagen Reviewed-by: Allan Sandfeld Jensen --- src/corelib/io/qfilesystemengine.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index a49d69d447..02aa2ff4b7 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -258,7 +258,7 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer) entryFlags |= QFileSystemMetaData::FileType; else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR) entryFlags |= QFileSystemMetaData::DirectoryType; - else + else if ((statBuffer.st_mode & S_IFMT) != S_IFBLK) entryFlags |= QFileSystemMetaData::SequentialType; // Attributes @@ -341,6 +341,18 @@ void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry) break; case DT_BLK: + knownFlagsMask = QFileSystemMetaData::LinkType + | QFileSystemMetaData::FileType + | QFileSystemMetaData::DirectoryType + | QFileSystemMetaData::BundleType + | QFileSystemMetaData::AliasType + | QFileSystemMetaData::SequentialType + | QFileSystemMetaData::ExistsAttribute; + + entryFlags = QFileSystemMetaData::ExistsAttribute; + + break; + case DT_CHR: case DT_FIFO: case DT_SOCK: -- cgit v1.2.3