diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-07 01:46:24 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-07 01:46:24 (GMT) |
commit | e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924 (patch) | |
tree | f130e76140457cf8071193278acd783d898c54fb /src | |
parent | b20ef0ade0aec89b969bd0ae7f754c680e390c67 (diff) | |
parent | 66733e95351f0088fd206a9215bde9d14510bc1e (diff) | |
download | Qt-e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924.zip Qt-e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924.tar.gz Qt-e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924.tar.bz2 |
Merge branch 'qt-4.7-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration into 4.7-integration
* 'qt-4.7-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration: (123 commits)
Added missing tests to tests/auto/*.pro
Compile with DirectFB version >= 1.2.0 && < 1.2.9
QDirectFBPaintEngine optimization
Add some warnings when using DISABLE/WARN in DFB
Fix build with Mesa 7.8's EGL implementatioon
Reset the byte order in the iconv codec after using it.
fix "using namespace" recursion crash
Fix for QTBUG-6659 Parent window accepts pointer events wrongly
If no IAP defined force IAP dialog
Fixed key mappings on X11
QDom: prevent infinite loop when cloning a DTD
Compile fix for Windows Mobile and OpenGLES2
QPrintPreviewDialog number of pages is partially blocked from view in OSX
QS60Style ignores widget palette when drawing highlighted widget text
Fix for QTBUG-8762 QApplication::setGraphicsSystem("raster") crashes.
Fixed crash at application exit when QProcess was used in Symbian
QMessageBox is not stretched to screen width if the content is narrow
Wrong dirty region after row selection in right-to-left mode in QTableView
Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit/qtwebkit-4.6 ( f3110d2f94c825477afac054ed448e45d47f5670 )
Tab to space fixes to qdilaog.cpp
...
Diffstat (limited to 'src')
95 files changed, 1427 insertions, 622 deletions
diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index cc0e04f..6a2e75f 100644 --- a/src/3rdparty/webkit/VERSION +++ b/src/3rdparty/webkit/VERSION @@ -8,4 +8,4 @@ The commit imported was from the and has the sha1 checksum - ffae5e11181a3961193fa21ea405851cad714d4b + f3110d2f94c825477afac054ed448e45d47f5670 diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index c9b622a..5654a18 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -26,7 +26,7 @@ symbian: { # RO text (code) section in qtwebkit.dll exceeds allocated space for gcce udeb target. # Move RW-section base address to start from 0xE00000 instead of the toolchain default 0x400000. - QMAKE_LFLAGS.ARMCC += --rw-base 0xE00000 + MMP_RULES += "LINKEROPTION armcc --rw-base 0xE00000" } include($$PWD/../WebKit.pri) diff --git a/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp index 714cac9..d13c9a9 100644 --- a/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/qt/PopupMenuQt.cpp @@ -39,7 +39,7 @@ #include <QGraphicsProxyWidget> #include <QGraphicsScene> #include <QGraphicsView> -#include <QGraphicsWebView> +#include <qgraphicswebview.h> #include <QListWidget> #include <QListWidgetItem> #include <QMenu> diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebelement.h b/src/3rdparty/webkit/WebKit/qt/Api/qwebelement.h index 3833070..13c341c 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebelement.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebelement.h @@ -20,11 +20,11 @@ #ifndef QWEBELEMENT_H #define QWEBELEMENT_H -#include <QString> -#include <QStringList> -#include <QRect> -#include <QVariant> -#include <QExplicitlySharedDataPointer> +#include <QtCore/qstring.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qrect.h> +#include <QtCore/qvariant.h> +#include <QtCore/qshareddata.h> #include "qwebkitglobal.h" namespace WebCore { diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index 1026ac5..e54c176 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,16 @@ +2010-03-04 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] qwebelement.h does not include QtCore headers correctly + https://bugs.webkit.org/show_bug.cgi?id=35748 + + The header files of QtCore must be included as QtCore/foo.h. + + See also http://bugreports.qt.nokia.com/browse/QTBUG-8661 + + * Api/qwebelement.h: + 2010-01-28 Kenneth Rohde Christiansen <kenneth@webkit.org> Reviewed by Simon Hausmann. diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index 7d2dde7..7afce5b 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -1434,9 +1434,6 @@ extern Q_GUI_EXPORT bool qt_win_ignoreNextMouseReleaseEvent; HRESULT WINAPI QAxClientSite::EnableModeless(BOOL fEnable) { -#if !defined(Q_OS_WINCE) - LockWindowUpdate(host->window()->winId()); -#endif EnableWindow(host->window()->winId(), fEnable); if (!fEnable) { @@ -1447,9 +1444,6 @@ HRESULT WINAPI QAxClientSite::EnableModeless(BOOL fEnable) QApplicationPrivate::leaveModal(host); } qt_win_ignoreNextMouseReleaseEvent = false; -#if !defined(Q_OS_WINCE) - LockWindowUpdate(0); -#endif return S_OK; } diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 0f73d9b..0fcdf96 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -299,6 +299,32 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState Q_GLOBAL_STATIC(QThreadStorage<QIconvCodec::IconvState *>, fromUnicodeState) +static bool setByteOrder(iconv_t cd) +{ +#if !defined(NO_BOM) + // give iconv() a BOM + char buf[4]; + ushort bom[] = { QChar::ByteOrderMark }; + + char *outBytes = buf; + char *inBytes = reinterpret_cast<char *>(bom); + size_t outBytesLeft = sizeof buf; + size_t inBytesLeft = sizeof bom; + +#if defined(GNU_LIBICONV) + const char **inBytesPtr = const_cast<const char **>(&inBytes); +#else + char **inBytesPtr = &inBytes; +#endif + + if (iconv(cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { + return false; + } +#endif // NO_BOM + + return true; +} + QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *convState) const { char *inBytes; @@ -325,17 +351,8 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt IconvState *&state = ts->localData(); if (!state) { state = new IconvState(QIconvCodec::createIconv_t(0, UTF16)); - if (state->cd != reinterpret_cast<iconv_t>(-1)) { - size_t outBytesLeft = len + 3; // +3 for the BOM - QByteArray ba(outBytesLeft, Qt::Uninitialized); - outBytes = ba.data(); - -#if !defined(NO_BOM) - // give iconv() a BOM - QChar bom[] = { QChar(QChar::ByteOrderMark) }; - inBytes = reinterpret_cast<char *>(bom); - inBytesLeft = sizeof(bom); - if (iconv(state->cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { + if (state->cd == reinterpret_cast<iconv_t>(-1)) { + if (!setByteOrder(state->cd)) { perror("QIconvCodec::convertFromUnicode: using ASCII for conversion, iconv failed for BOM"); iconv_close(state->cd); @@ -343,7 +360,6 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt return QString(uc, len).toAscii(); } -#endif // NO_BOM } } if (state->cd == reinterpret_cast<iconv_t>(-1)) { @@ -422,6 +438,7 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt // reset to initial state iconv(state->cd, 0, &inBytesLeft, 0, &outBytesLeft); + setByteOrder(state->cd); ba.resize(ba.size() - outBytesLeft); diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index d2546a7..f7aea36 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -299,7 +299,9 @@ public: MacWindowToolBarButtonHint = 0x10000000, BypassGraphicsProxyWidget = 0x20000000, WindowOkButtonHint = 0x00080000, - WindowCancelButtonHint = 0x00100000 + WindowCancelButtonHint = 0x00100000, + WindowSoftkeysVisibleHint = 0x40000000, + WindowSoftkeysRespondHint = 0x80000000 #ifdef QT3_SUPPORT , diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index c5b5998..74144b0 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1623,22 +1623,22 @@ \value Key_OpenUrl \value Key_LaunchMail \value Key_LaunchMedia - \value Key_Launch0 - \value Key_Launch1 - \value Key_Launch2 - \value Key_Launch3 - \value Key_Launch4 - \value Key_Launch5 - \value Key_Launch6 - \value Key_Launch7 - \value Key_Launch8 - \value Key_Launch9 - \value Key_LaunchA - \value Key_LaunchB - \value Key_LaunchC - \value Key_LaunchD - \value Key_LaunchE - \value Key_LaunchF + \value Key_Launch0 On X11 this key is mapped to "My Computer" (XF86XK_MyComputer) key for legacy reasons. + \value Key_Launch1 On X11 this key is mapped to "Calculator" (XF86XK_Calculator) key for legacy reasons. + \value Key_Launch2 On X11 this key is mapped to XF86XK_Launch0 key for legacy reasons. + \value Key_Launch3 On X11 this key is mapped to XF86XK_Launch1 key for legacy reasons. + \value Key_Launch4 On X11 this key is mapped to XF86XK_Launch2 key for legacy reasons. + \value Key_Launch5 On X11 this key is mapped to XF86XK_Launch3 key for legacy reasons. + \value Key_Launch6 On X11 this key is mapped to XF86XK_Launch4 key for legacy reasons. + \value Key_Launch7 On X11 this key is mapped to XF86XK_Launch5 key for legacy reasons. + \value Key_Launch8 On X11 this key is mapped to XF86XK_Launch6 key for legacy reasons. + \value Key_Launch9 On X11 this key is mapped to XF86XK_Launch7 key for legacy reasons. + \value Key_LaunchA On X11 this key is mapped to XF86XK_Launch8 key for legacy reasons. + \value Key_LaunchB On X11 this key is mapped to XF86XK_Launch9 key for legacy reasons. + \value Key_LaunchC On X11 this key is mapped to XF86XK_LaunchA key for legacy reasons. + \value Key_LaunchD On X11 this key is mapped to XF86XK_LaunchB key for legacy reasons. + \value Key_LaunchE On X11 this key is mapped to XF86XK_LaunchC key for legacy reasons. + \value Key_LaunchF On X11 this key is mapped to XF86XK_LaunchD key for legacy reasons. \value Key_MonBrightnessUp \value Key_MonBrightnessDown \value Key_KeyboardLightOnOff @@ -1664,7 +1664,7 @@ \value Key_ApplicationRight \value Key_Book \value Key_CD - \value Key_Calculator + \value Key_Calculator On X11 this key is not mapped for legacy reasons. Use Qt::Key_Launch1 instead. \value Key_ToDoList \value Key_ClearGrab \value Key_Close @@ -2147,6 +2147,14 @@ \value WindowCancelButtonHint Adds a Cancel button to the window decoration of a dialog. Only supported for Windows CE. + \value WindowSoftkeysVisibleHint Makes softkeys visible when widget is fullscreen. + Only supported for Symbian. + + \value WindowSoftkeysRespondHint Makes softkeys to receive key events even + when invisible. With this hint the softkey actions are triggered + even the softkeys are invisible i.e. the window is displayed with + \c showFullscreen(). Only supported for Symbian. + \value WindowType_Mask A mask for extracting the window type part of the window flags. diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 1672dfc..070edb4 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -147,6 +147,8 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) return path; #endif #if defined(Q_OS_LINUX) || defined(Q_OS_SYMBIAN) || defined(Q_OS_MAC) + // ... but Linux with uClibc does not have it +#if !defined(__UCLIBC__) char *ret = 0; #if defined(Q_OS_MAC) // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. @@ -173,6 +175,7 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) return canonicalPath; } #endif +#endif QFileInfo fi; const QChar slash(QLatin1Char('/')); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index d2fa744..1331f54 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -668,6 +668,16 @@ bool QFSFileEnginePrivate::doStat() const could_stat = (QT_FSTAT(QT_FILENO(fh), &st) == 0); } else if (fd == -1) { // ### actually covers two cases: d->fh and when the file is not open +#if defined(Q_OS_SYMBIAN) + // Optimisation for Symbian where fileFlags() calls both doStat() and isSymlink(), but rarely on real links. + // When the filename is not a link, lstat will return the same info as stat, but this also removes + // any need for a further call to lstat to check if the file is a link. + need_lstat = false; + could_stat = (QT_LSTAT(nativeFilePath.constData(), &st) == 0); + is_link = could_stat ? S_ISLNK(st.st_mode) : false; + // if it turns out this was a link, we can call stat too. + if (is_link) +#endif could_stat = (QT_STAT(nativeFilePath.constData(), &st) == 0); } else { could_stat = (QT_FSTAT(fd, &st) == 0); diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index 07d10ad..adc87fb 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -371,6 +371,7 @@ QProcessActive::QProcessActive() // Called from ProcessManagerThread QProcessActive::~QProcessActive() { + Cancel(); process = NULL; pproc = NULL; } @@ -477,6 +478,7 @@ QProcessManagerMediator::QProcessManagerMediator() // Called from ProcessManagerThread QProcessManagerMediator::~QProcessManagerMediator() { + Cancel(); processManagerThread.Close(); currentCommand = ENoCommand; currentObserver = NULL; diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 1d7be79..191be6c 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -733,7 +733,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla } TInt error; - handledSymbianEvent = CActiveScheduler::RunIfReady(error, CActive::EPriorityIdle); + handledSymbianEvent = CActiveScheduler::RunIfReady(error, KMinTInt); if (error) { qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error); CActiveScheduler::Current()->Error(error); diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index ecffe99..312c4b2 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -974,7 +974,7 @@ QByteArray QMetaObject::normalizedType(const char *type) if (!type || !*type) return result; - QVarLengthArray<char> stackbuf(int(strlen(type)) + 1); + QVarLengthArray<char> stackbuf(qstrlen(type) + 1); qRemoveWhitespace(type, stackbuf.data()); int templdepth = 0; qNormalizeType(stackbuf.data(), templdepth, result); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8e4ec7c..389e6e7 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3279,12 +3279,14 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign const int method = c->method; QObjectPrivate::Sender currentSender; - currentSender.sender = sender; - currentSender.signal = signal_absolute_index; - currentSender.ref = 1; + const bool receiverInSameThread = currentThreadData == receiver->d_func()->threadData; QObjectPrivate::Sender *previousSender = 0; - if (currentThreadData == receiver->d_func()->threadData) + if (receiverInSameThread) { + currentSender.sender = sender; + currentSender.signal = signal_absolute_index; + currentSender.ref = 1; previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); + } locker.unlock(); if (qt_signal_spy_callback_set.slot_begin_callback != 0) { @@ -3300,8 +3302,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); } QT_CATCH(...) { locker.relock(); - - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); + if (receiverInSameThread) + QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); --connectionLists->inUse; Q_ASSERT(connectionLists->inUse >= 0); @@ -3316,7 +3318,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign locker.relock(); - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); + if (receiverInSameThread) + QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); if (connectionLists->orphaned) break; diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 227a60d..07c9e53 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -484,9 +484,13 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) * QMetaType::VoidStar, QMetaType::QObjectStar and so forth, is that it wouldn't include * user defined pointer types. */ const char *const typeName = QMetaType::typeName(a->type); - if (typeName[qstrlen(typeName) - 1] == '*') + uint typeNameLen = qstrlen(typeName); + if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr); + if (a->is_null && b->is_null) + return true; + return a_ptr == b_ptr; } diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 80b50fc..677412e 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -95,7 +95,7 @@ class Q_CORE_EXPORT QMutexLocker { public: inline explicit QMutexLocker(QMutex *m) - : mtx(m) + : val(reinterpret_cast<quintptr>(m)) { Q_ASSERT_X((val & quintptr(1u)) == quintptr(0), "QMutexLocker", "QMutex pointer is misaligned"); @@ -105,19 +105,19 @@ public: inline void unlock() { - if (mtx) { + if (val) { if ((val & quintptr(1u)) == quintptr(1u)) { val &= ~quintptr(1u); - mtx->unlock(); + mutex()->unlock(); } } } inline void relock() { - if (mtx) { + if (val) { if ((val & quintptr(1u)) == quintptr(0u)) { - mtx->lock(); + mutex()->lock(); val |= quintptr(1u); } } @@ -140,10 +140,7 @@ public: private: Q_DISABLE_COPY(QMutexLocker) - union { - QMutex *mtx; - quintptr val; - }; + quintptr val; }; #else // QT_NO_THREAD diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h index 278b8d4..9521ac3 100644 --- a/src/corelib/thread/qreadwritelock.h +++ b/src/corelib/thread/qreadwritelock.h @@ -96,19 +96,19 @@ public: inline void unlock() { - if (q_lock) { + if (q_val) { if ((q_val & quintptr(1u)) == quintptr(1u)) { q_val &= ~quintptr(1u); - q_lock->unlock(); + readWriteLock()->unlock(); } } } inline void relock() { - if (q_lock) { + if (q_val) { if ((q_val & quintptr(1u)) == quintptr(0u)) { - q_lock->lockForRead(); + readWriteLock()->lockForRead(); q_val |= quintptr(1u); } } @@ -119,14 +119,11 @@ public: private: Q_DISABLE_COPY(QReadLocker) - union { - QReadWriteLock *q_lock; - quintptr q_val; - }; + quintptr q_val; }; inline QReadLocker::QReadLocker(QReadWriteLock *areadWriteLock) - : q_lock(areadWriteLock) + : q_val(reinterpret_cast<quintptr>(areadWriteLock)) { Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), "QReadLocker", "QReadWriteLock pointer is misaligned"); @@ -143,19 +140,19 @@ public: inline void unlock() { - if (q_lock) { + if (q_val) { if ((q_val & quintptr(1u)) == quintptr(1u)) { q_val &= ~quintptr(1u); - q_lock->unlock(); + readWriteLock()->unlock(); } } } inline void relock() { - if (q_lock) { + if (q_val) { if ((q_val & quintptr(1u)) == quintptr(0u)) { - q_lock->lockForWrite(); + readWriteLock()->lockForWrite(); q_val |= quintptr(1u); } } @@ -167,14 +164,11 @@ public: private: Q_DISABLE_COPY(QWriteLocker) - union{ - QReadWriteLock *q_lock; - quintptr q_val; - }; + quintptr q_val; }; inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock) - : q_lock(areadWriteLock) + : q_val(reinterpret_cast<quintptr>(areadWriteLock)) { Q_ASSERT_X((q_val & quintptr(1u)) == quintptr(0), "QWriteLocker", "QReadWriteLock pointer is misaligned"); diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 20ad444..eb104a8 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -523,7 +523,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, \endtable In the mode Wildcard, the wildcard characters cannot be - escaped. In the mode WildcardUnix, the character '\' escapes the + escaped. In the mode WildcardUnix, the character '\\' escapes the wildcard. For example if we are in wildcard mode and have strings which @@ -3779,7 +3779,7 @@ static void invalidateEngine(QRegExpPrivate *priv) \value WildcardUnix This is similar to Wildcard but with the behavior of a Unix shell. The wildcard characters can be escaped - with the character "\". + with the character "\\". \value FixedString The pattern is a fixed string. This is equivalent to using the RegExp pattern on a string in diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index e9b7b9a..eff87e8 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3227,7 +3227,7 @@ QString QString::section(const QRegExp ®, int start, int end, SectionFlags fl if (!empty || !(flags & SectionSkipEmpty)) x++; } - if((flags & SectionIncludeLeadingSep)) { + if((flags & SectionIncludeLeadingSep) && first_i < sections.size()) { const qt_section_chunk §ion = sections.at(first_i); ret.prepend(section.string.left(section.length)); } diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index ce3e1a0..abaa486 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -491,6 +491,12 @@ bool QDBusConnection::callWithCallback(const QDBusMessage &message, QObject *rec its return value, which will be either of type QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage. + If no reply is received within \a timeout milliseconds, an automatic + error will be delivered indicating the expiration of the call. + The default \a timeout is -1, which will be replaced with an + implementation-defined value that is suitable for inter-process + communications (generally, 25 seconds). + See the QDBusInterface::call() function for a more friendly way of placing calls. @@ -526,9 +532,14 @@ QDBusMessage QDBusConnection::call(const QDBusMessage &message, QDBus::CallMode Sends the \a message over this connection and returns immediately. This function is suitable for method calls only. It returns an object of type QDBusPendingCall which can be used to - track the status of the reply. The \a timeout parameter is used to - determine when an auto-generated error reply may be emitted and is - also the upper limit for waiting in QDBusPendingCall::waitForFinished(). + track the status of the reply. + + If no reply is received within \a timeout milliseconds, an automatic + error will be delivered indicating the expiration of the call. The + default \a timeout is -1, which will be replaced with an + implementation-defined value that is suitable for inter-process + communications (generally, 25 seconds). This timeout is also the + upper limit for waiting in QDBusPendingCall::waitForFinished(). See the QDBusInterface::asyncCall() function for a more friendly way of placing calls. diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index fb0dba4..2d75913 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -808,11 +808,11 @@ void QDialog::setVisible(bool visible) void QDialog::showEvent(QShowEvent *event) { if (!event->spontaneous() && !testAttribute(Qt::WA_Moved)) { - Qt::WindowStates state = windowState(); + Qt::WindowStates state = windowState(); adjustPosition(parentWidget()); setAttribute(Qt::WA_Moved, false); // not really an explicit position - if (state != windowState()) - setWindowState(state); + if (state != windowState()) + setWindowState(state); } } diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index ed437ff..121ba62 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -314,6 +314,7 @@ void QMessageBoxPrivate::updateSize() } width = hardLimit; } + } #ifdef Q_WS_S60 // in S60 portait messageBoxes should always occupy maximum width if (QApplication::desktop()->size().height() > QApplication::desktop()->size().width()){ @@ -323,7 +324,6 @@ void QMessageBoxPrivate::updateSize() width = qMin(QApplication::desktop()->size().height(), hardLimit); } #endif - } if (informativeLabel) { label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); diff --git a/src/gui/dialogs/qprintpreviewdialog.cpp b/src/gui/dialogs/qprintpreviewdialog.cpp index 6723b53..f21343e 100644 --- a/src/gui/dialogs/qprintpreviewdialog.cpp +++ b/src/gui/dialogs/qprintpreviewdialog.cpp @@ -273,7 +273,20 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer) QWidget *pageEdit = new QWidget(toolbar); QVBoxLayout *vboxLayout = new QVBoxLayout; vboxLayout->setContentsMargins(0, 0, 0, 0); +#ifdef Q_WS_MAC + // We query the widgets about their size and then we fix the size. + // This should do the trick for the laying out part... + QSize pageNumEditSize, pageNumLabelSize; + pageNumEditSize = pageNumEdit->minimumSizeHint(); + pageNumLabelSize = pageNumLabel->minimumSizeHint(); + pageNumEdit->resize(pageNumEditSize); + pageNumLabel->resize(pageNumLabelSize); +#endif QFormLayout *formLayout = new QFormLayout; +#ifdef Q_WS_MAC + // We have to change the growth policy in Mac. + formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); +#endif formLayout->setWidget(0, QFormLayout::LabelRole, pageNumEdit); formLayout->setWidget(0, QFormLayout::FieldRole, pageNumLabel); vboxLayout->addLayout(formLayout); diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index f500bd4..7dad9fe 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -55,10 +55,14 @@ QT_BEGIN_INCLUDE_NAMESPACE +#if defined(QT_OPENGL_ES_2) +# include <GLES2/gl2.h> +#endif + #if defined(QT_GLES_EGL) -#include <GLES/egl.h> +# include <GLES/egl.h> #else -#include <EGL/egl.h> +# include <EGL/egl.h> #endif #if defined(Q_WS_X11) diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp index 636f469..b5d3103 100644 --- a/src/gui/egl/qeglproperties.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -39,16 +39,13 @@ ** ****************************************************************************/ -#include "qeglproperties_p.h" - -QT_BEGIN_NAMESPACE - #include <QtCore/qdebug.h> #include <QtCore/qstringlist.h> #include "qeglproperties_p.h" #include "qeglcontext_p.h" +QT_BEGIN_NAMESPACE // Initialize a property block. QEglProperties::QEglProperties() diff --git a/src/gui/embedded/directfb.pri b/src/gui/embedded/directfb.pri index d6d77b4..75d693e 100644 --- a/src/gui/embedded/directfb.pri +++ b/src/gui/embedded/directfb.pri @@ -15,7 +15,7 @@ #DEFINES += QT_DIRECTFB_TIMING #DEFINES += QT_NO_DIRECTFB_OPAQUE_DETECTION #DEFINES += QT_NO_DIRECTFB_STRETCHBLIT -#DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS|DRAW_ROUNDED_RECT|DRAW_STATICTEXT +DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS|DRAW_ROUNDED_RECT|DRAW_STATICTEXT #DEFINES += \"QT_DIRECTFB_WARN_ON_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\" #DEFINES += \"QT_DIRECTFB_DISABLE_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\" diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp index 65a3fb5..a3fe1ab 100644 --- a/src/gui/embedded/qscreen_qws.cpp +++ b/src/gui/embedded/qscreen_qws.cpp @@ -2740,7 +2740,7 @@ void QScreen::compose(int level, const QRegion &exposed, QRegion &blend, default: break; } - spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_SourceOver); + spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_Source); spanData.dx = off.x(); spanData.dy = off.y(); } else if (!surface->isBuffered()) { diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 4f06f80..b712016 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -641,10 +641,10 @@ are children of a modal panel are not blocked. The values are: - + \value NonModal The panel is not modal and does not block input to other panels. This is the default value for panels. - + \value PanelModal The panel is modal to a single item hierarchy and blocks input to its parent pane, all grandparent panels, and all siblings of its parent and grandparent panels. @@ -2182,6 +2182,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Certain properties are dropped as an item becomes invisible. + bool hasFocus = q_ptr->hasFocus(); if (!newVisible) { if (scene) { if (scene->d_func()->mouseGrabberItems.contains(q)) @@ -2191,7 +2192,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo if (q->isPanel() && panelModality != QGraphicsItem::NonModal) scene->d_func()->leaveModal(q_ptr); } - if (q_ptr->hasFocus() && scene) { + if (hasFocus && scene) { // Hiding the closest non-panel ancestor of the focus item QGraphicsItem *focusItem = scene->focusItem(); bool clear = true; @@ -2204,7 +2205,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel()); } if (clear) - q_ptr->clearFocus(); + clearFocusHelper(/* giveFocusToParent = */ false); } if (q_ptr->isSelected()) q_ptr->setSelected(false); @@ -2242,26 +2243,45 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Enable subfocus - if (scene && newVisible) { - QGraphicsItem *p = parent; - bool done = false; - while (p) { - if (p->flags() & QGraphicsItem::ItemIsFocusScope) { - QGraphicsItem *fsi = p->d_ptr->focusScopeItem; - if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) { - done = true; - while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible()) - fsi = fsi->d_ptr->focusScopeItem; - scene->setFocusItem(fsi); + if (scene) { + if (newVisible) { + // Item is shown + QGraphicsItem *p = parent; + bool done = false; + while (p) { + if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + QGraphicsItem *fsi = p->d_ptr->focusScopeItem; + if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) { + done = true; + while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible()) + fsi = fsi->d_ptr->focusScopeItem; + fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true, + /* focusFromShow = */ true); + } + break; } - break; + p = p->d_ptr->parent; } - p = p->d_ptr->parent; - } - if (!done) { - QGraphicsItem *fi = subFocusItem; - if (fi && fi != scene->focusItem()) { - scene->setFocusItem(fi); + if (!done) { + QGraphicsItem *fi = subFocusItem; + if (fi && fi != scene->focusItem()) { + scene->setFocusItem(fi); + } + } + } else { + // Item is hidden + if (hasFocus) { + QGraphicsItem *p = parent; + while (p) { + if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + if (p->d_ptr->visible) { + p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true, + /* focusFromShow = */ true); + } + break; + } + p = p->d_ptr->parent; + } } } } @@ -3112,13 +3132,13 @@ bool QGraphicsItem::hasFocus() const */ void QGraphicsItem::setFocus(Qt::FocusReason focusReason) { - d_ptr->setFocusHelper(focusReason, /* climb = */ true); + d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromShow = */ false); } /*! \internal */ -void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb) +void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow) { // Disabled / unfocusable items cannot accept focus. if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable)) @@ -3138,7 +3158,7 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim while (p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) { p->d_ptr->focusScopeItem = q_ptr; - if (!p->focusItem()) { + if (!p->focusItem() && !focusFromShow) { // If you call setFocus on a child of a focus scope that // doesn't currently have a focus item, then stop. return; @@ -3179,24 +3199,35 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim */ void QGraphicsItem::clearFocus() { - // Pass focus to the closest parent focus scope. - if (!d_ptr->inDestructor) { - QGraphicsItem *p = d_ptr->parent; - while (p) { - if (p->flags() & ItemIsFocusScope) { - p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false); - return; + d_ptr->clearFocusHelper(/* giveFocusToParent = */ true); +} + +/*! + \internal +*/ +void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent) +{ + if (giveFocusToParent) { + // Pass focus to the closest parent focus scope + if (!inDestructor) { + QGraphicsItem *p = parent; + while (p) { + if (p->flags() & QGraphicsItem::ItemIsFocusScope) { + p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false, + /* focusFromShow = */ false); + return; + } + p = p->d_ptr->parent; } - p = p->d_ptr->parent; } } // Invisible items with focus must explicitly clear subfocus. - d_ptr->clearSubFocus(this); + clearSubFocus(q_ptr); - if (hasFocus()) { + if (q_ptr->hasFocus()) { // If this item has the scene's input focus, clear it. - d_ptr->scene->setFocusItem(0); + scene->setFocusItem(0); } } @@ -10817,6 +10848,7 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) } } +// sourceRect must be in the given coordinate system QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const { QRectF effectRectF; @@ -10826,7 +10858,8 @@ QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem sy if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) { if (info) { - effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates)); + QRectF deviceRect = system == Qt::DeviceCoordinates ? sourceRect : info->painter->worldTransform().mapRect(sourceRect); + effectRectF = item->graphicsEffect()->boundingRectFor(deviceRect); if (unpadded) *unpadded = (effectRectF.size() == sourceRect.size()); if (info && system == Qt::LogicalCoordinates) @@ -10875,30 +10908,6 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP return static_cast<QGraphicsPixmapItem *>(item)->pixmap(); } - if (deviceCoordinates) { - // Clip to viewport rect. - int left, top, right, bottom; - effectRect.getCoords(&left, &top, &right, &bottom); - if (left < 0) { - if (offset) - offset->rx() += -left; - effectRect.setX(0); - } - if (top < 0) { - if (offset) - offset->ry() += -top; - effectRect.setY(0); - } - // NB! We use +-1 for historical reasons (see QRect documentation). - QPaintDevice *device = info->painter->device(); - const int deviceWidth = device->width(); - const int deviceHeight = device->height(); - if (right + 1 > deviceWidth) - effectRect.setRight(deviceWidth - 1); - if (bottom + 1 > deviceHeight) - effectRect.setBottom(deviceHeight -1); - - } if (effectRect.isEmpty()) return QPixmap(); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 4c4bfaf..de8cf56 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -414,7 +414,8 @@ public: inline void markParentDirty(bool updateBoundingRect = false); - void setFocusHelper(Qt::FocusReason focusReason, bool climb); + void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow); + void clearFocusHelper(bool giveFocusToParent); void setSubFocus(QGraphicsItem *rootItem = 0); void clearSubFocus(QGraphicsItem *rootItem = 0); void resetFocusProxy(); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6bc02cc..fc311f5 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4728,31 +4728,18 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (sourced->currentCachedSystem() != Qt::LogicalCoordinates && sourced->lastEffectTransform != painter->worldTransform()) { - bool unclipped = false; if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate && painter->worldTransform().type() <= QTransform::TxTranslate) { - QRectF itemRect = item->boundingRect(); - if (!item->d_ptr->children.isEmpty()) - itemRect |= item->childrenBoundingRect(); + QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates); + QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect); - QRectF oldSourceRect = sourced->lastEffectTransform.mapRect(itemRect); - QRectF newSourceRect = painter->worldTransform().mapRect(itemRect); - - QRect oldEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), oldSourceRect); - QRect newEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), newSourceRect); - - QRect deviceRect(0, 0, painter->device()->width(), painter->device()->height()); - if (deviceRect.contains(oldEffectRect) && deviceRect.contains(newEffectRect)) { - sourced->setCachedOffset(newEffectRect.topLeft()); - unclipped = true; - } + sourced->setCachedOffset(effectRect.topLeft()); + } else { + sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged); } sourced->lastEffectTransform = painter->worldTransform(); - - if (!unclipped) - sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged); } item->d_ptr->graphicsEffect->draw(painter); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 1ced3d7..a767987 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3360,12 +3360,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event) backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); if (viewTransformed) backgroundPainter.setTransform(viewTransform); -#ifdef Q_WS_X11 -#undef X11 - if (backgroundPainter.paintEngine()->type() != QPaintEngine::X11) -#define X11 qt_x11Data -#endif - backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect(); drawBackground(&backgroundPainter, backgroundExposedSceneRect); d->backgroundPixmapExposed = QRegion(); diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index bf6eb8d..fad51f4 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -982,7 +982,9 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) icon = *cachedIcon; } - if (icon.availableSizes().isEmpty()) + // Note the qapp check is to allow lazy loading of static icons + // Supporting fallbacks will not work for this case. + if (qApp && icon.availableSizes().isEmpty()) return fallback; return icon; diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index b35e80a..72ec2e8 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -85,19 +85,30 @@ static QString fallbackTheme() } QIconLoader::QIconLoader() : - m_themeKey(1), m_supportsSvg(false) + m_themeKey(1), m_supportsSvg(false), m_initialized(false) { - m_systemTheme = qt_guiPlatformPlugin()->systemIconThemeName(); - if (m_systemTheme.isEmpty()) - m_systemTheme = fallbackTheme(); +} + +// We lazily initialize the loader to make static icons +// work. Though we do not officially support this. +void QIconLoader::ensureInitialized() +{ + if (!m_initialized) { + m_initialized = true; + + Q_ASSERT(qApp); + m_systemTheme = qt_guiPlatformPlugin()->systemIconThemeName(); + if (m_systemTheme.isEmpty()) + m_systemTheme = fallbackTheme(); #ifndef QT_NO_LIBRARY - QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid, - QLatin1String("/iconengines"), - Qt::CaseInsensitive); - if (iconFactoryLoader.keys().contains(QLatin1String("svg"))) - m_supportsSvg = true; + QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid, + QLatin1String("/iconengines"), + Qt::CaseInsensitive); + if (iconFactoryLoader.keys().contains(QLatin1String("svg"))) + m_supportsSvg = true; #endif //QT_NO_LIBRARY + } } QIconLoader *QIconLoader::instance() @@ -339,6 +350,9 @@ bool QIconLoaderEngine::hasIcon() const // Lazily load the icon void QIconLoaderEngine::ensureLoaded() { + + iconLoaderInstance()->ensureInitialized(); + if (!(iconLoaderInstance()->themeKey() == m_key)) { while (!m_entries.isEmpty()) diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h index 19f2dda..a6b5f5b 100644 --- a/src/gui/image/qiconloader_p.h +++ b/src/gui/image/qiconloader_p.h @@ -169,6 +169,7 @@ public: static QIconLoader *instance(); void updateSystemTheme(); void invalidateKey() { m_themeKey++; } + void ensureInitialized(); private: QThemeIconEntries findIconHelper(const QString &themeName, @@ -176,6 +177,7 @@ private: QStringList &visited) const; uint m_themeKey; bool m_supportsSvg; + bool m_initialized; mutable QString m_userTheme; mutable QString m_systemTheme; diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp index 517fcb0..521e348 100644 --- a/src/gui/image/qimagepixmapcleanuphooks.cpp +++ b/src/gui/image/qimagepixmapcleanuphooks.cpp @@ -96,6 +96,11 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook) void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* pmd) { QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); + // the global destructor for the pixmap and image hooks might have + // been called already if the app is "leaking" global + // pixmaps/images + if (!h) + return; for (int i = 0; i < h->pixmapModificationHooks.count(); ++i) h->pixmapModificationHooks[i](pmd); @@ -106,6 +111,11 @@ void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* p void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(QPixmapData* pmd) { QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks(); + // the global destructor for the pixmap and image hooks might have + // been called already if the app is "leaking" global + // pixmaps/images + if (!h) + return; for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i) h->pixmapDestructionHooks[i](pmd); diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index ae62f06..474cd2e 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -831,21 +831,14 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers if (QPixmapCache::find(key, *this)) return true; - bool ok; - - if (data) { - ok = data->fromFile(fileName, format, flags); - } else { - QScopedPointer<QPixmapData> tmp(QPixmapData::create(0, 0, QPixmapData::PixmapType)); - ok = tmp->fromFile(fileName, format, flags); - if (ok) - data = tmp.take(); - } - - if (ok) + QScopedPointer<QPixmapData> tmp(QPixmapData::create(0, 0, data ? data->type : QPixmapData::PixmapType)); + if (tmp->fromFile(fileName, format, flags)) { + data = tmp.take(); QPixmapCache::insert(key, *this); + return true; + } - return ok; + return false; } /*! @@ -2046,12 +2039,16 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags) over the one you grab, you get pixels from the overlying window, too. The mouse cursor is generally not grabbed. - Note on X11that if the given \a window doesn't have the same depth + Note on X11 that if the given \a window doesn't have the same depth as the root window, and another window partially or entirely obscures the one you grab, you will \e not get pixels from the overlying window. The contents of the obscured areas in the pixmap will be undefined and uninitialized. + On Windows Vista and above grabbing a layered window, which is + created by setting the Qt::WA_TranslucentBackground attribute, will + not work. Instead grabbing the desktop widget should work. + \warning In general, grabbing an area outside the screen is not safe. This depends on the underlying window system. diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 0abf51f..5355ad3 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -777,6 +777,9 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp Q_GUI_EXPORT QImage qt_halfScaled(const QImage &source) { + if (source.width() < 2 || source.height() < 2) + return QImage(); + QImage srcImage = source; if (source.format() == QImage::Format_Indexed8) { @@ -869,7 +872,7 @@ Q_GUI_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, boo } qreal scale = 1; - if (radius >= 4) { + if (radius >= 4 && blurImage.width() >= 2 && blurImage.height() >= 2) { blurImage = qt_halfScaled(blurImage); scale = 2; radius *= qreal(0.5); diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 1ac8ace..cc60246 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -551,6 +551,21 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, m_formatRetriever = &aInlineTextFormatRetriever; m_pointerHandler = &aPointerEventHandlerDuringInlineEdit; + // With T9 aInitialInlineText is typically empty when StartFepInlineEditL is called, + // but FEP requires that selected text is always removed at StartFepInlineEditL. + // Let's remove the selected text if aInitialInlineText is empty and there is selected text + if (m_preeditString.isEmpty()) { + int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt(); + int replacementLength = qAbs(m_cursorPos-anchor); + if (replacementLength > 0) { + int replacementStart = m_cursorPos < anchor ? 0 : -replacementLength; + QList<QInputMethodEvent::Attribute> clearSelectionAttributes; + QInputMethodEvent clearSelectionEvent(QLatin1String(""), clearSelectionAttributes); + clearSelectionEvent.setCommitString(QLatin1String(""), replacementStart, replacementLength); + sendEvent(clearSelectionEvent); + } + } + applyFormat(&attributes); attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index bc6db90..2faf755 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -2568,6 +2568,7 @@ void QAbstractItemView::updateEditorGeometries() QStyleOptionViewItemV4 option = d->viewOptionsV4(); QList<QEditorInfo>::iterator it = d->editors.begin(); QWidgetList editorsToRelease; + QWidgetList editorsToHide; while (it != d->editors.end()) { QModelIndex index = it->index; QWidget *editor = it->editor; @@ -2579,7 +2580,7 @@ void QAbstractItemView::updateEditorGeometries() if (delegate) delegate->updateEditorGeometry(editor, option, index); } else { - editor->hide(); + editorsToHide << editor; } ++it; } else { @@ -2588,8 +2589,11 @@ void QAbstractItemView::updateEditorGeometries() } } - //we release the editor outside of the loop because it might change the focus and try + //we hide and release the editor outside of the loop because it might change the focus and try //to change the d->editors list. + for (int i = 0; i < editorsToHide.count(); ++i) { + editorsToHide.at(i)->hide(); + } for (int i = 0; i < editorsToRelease.count(); ++i) { d->releaseEditor(editorsToRelease.at(i)); } @@ -3046,6 +3050,7 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget if (!d->isIndexValid(index)) return; if (QWidget *oldWidget = indexWidget(index)) { + d->persistent.remove(oldWidget); d->removeEditor(oldWidget); oldWidget->deleteLater(); } diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 9069ce4..7d8e103 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -1297,14 +1297,8 @@ bool QItemDelegate::editorEvent(QEvent *event, return false; } - Qt::CheckState state; - if ( flags & Qt::ItemIsTristate ) { - state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 ); - } else { - state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked + Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked : Qt::Checked); - } - return model->setData(index, state, Qt::CheckStateRole); } diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index 9aac554..880f8ab 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -747,13 +747,8 @@ bool QStyledItemDelegate::editorEvent(QEvent *event, return false; } - Qt::CheckState state; - if ( flags & Qt::ItemIsTristate ) { - state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 ); - } else { - state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked + Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked : Qt::Checked); - } return model->setData(index, state, Qt::CheckStateRole); } diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index bdc1205..46fd9d0 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -1908,6 +1908,7 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co width, rowHeight(r))); } } else { // nothing moved + const int gridAdjust = showGrid() ? 1 : 0; for (int i = 0; i < selection.count(); ++i) { QItemSelectionRange range = selection.at(i); if (range.parent() != d->root || !range.isValid()) @@ -1916,9 +1917,16 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co const int rtop = rowViewportPosition(range.top()); const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom()); - const int rleft = columnViewportPosition(range.left()); - const int rright = columnViewportPosition(range.right()) + columnWidth(range.right()); - selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright, rbottom)); + int rleft; + int rright; + if (isLeftToRight()) { + rleft = columnViewportPosition(range.left()); + rright = columnViewportPosition(range.right()) + columnWidth(range.right()); + } else { + rleft = columnViewportPosition(range.right()); + rright = columnViewportPosition(range.left()) + columnWidth(range.left()); + } + selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright - 1 - gridAdjust, rbottom - 1 - gridAdjust)); if (d->hasSpans()) { foreach (QSpanCollection::Span *s, d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) { diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 8653dec..6d71cfe 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -543,6 +543,7 @@ public: const QList<QTouchEvent::TouchPoint> &touchPoints); #if defined(Q_WS_WIN) + static bool HasTouchSupport; static PtrRegisterTouchWindow RegisterTouchWindow; static PtrGetTouchInputInfo GetTouchInputInfo; static PtrCloseTouchInputHandle CloseTouchInputHandle; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index baefdfd..ccc39c9 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -597,9 +597,9 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, keyEvent.iCode); int keyCode; - if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used - keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); - } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { + if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used + keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); + } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { // Normal characters keys. keyCode = s60Keysym; } else { @@ -966,13 +966,26 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle()); #ifdef Q_WS_S60 // If widget is fullscreen/minimized, hide status pane and button container otherwise show them. - CEikStatusPane* statusPane = S60->statusPane(); - CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); + CEikStatusPane *statusPane = S60->statusPane(); + CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer(); TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); if (statusPane) statusPane->MakeVisible(visible); - if (buttonGroup) - buttonGroup->MakeVisible(visible); + if (buttonGroup) { + // Visibility + const TBool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; + const TBool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint; + buttonGroup->MakeVisible(visible || (isFullscreen && cbaVisibilityHint)); + + // Responsiviness + CEikCba *cba = static_cast<CEikCba *>( buttonGroup->ButtonGroup() ); // downcast from MEikButtonGroup + TUint cbaFlags = cba->ButtonGroupFlags(); + if(qwidget->windowFlags() & Qt::WindowSoftkeysRespondHint) + cbaFlags |= EAknCBAFlagRespondWhenInvisible; + else + cbaFlags &= ~EAknCBAFlagRespondWhenInvisible; + cba->SetButtonGroupFlags(cbaFlags); + } #endif } else if (QApplication::activeWindow() == qwidget->window()) { if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) { @@ -1016,6 +1029,16 @@ void QSymbianControl::HandleResourceChange(int resourceType) } else if (qwidget->isMaximized()) { TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); SetExtent(r.iTl, r.Size()); + } else if (!qwidget->isMinimized()){ // Normal geometry + if (!qwidget->testAttribute(Qt::WA_Resized)) { + qwidget->adjustSize(); + qwidget->setAttribute(Qt::WA_Resized, false); //not a user resize + } + if (!qwidget->testAttribute(Qt::WA_Moved)) { + TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); + SetPosition(r.iTl); + qwidget->setAttribute(Qt::WA_Moved, false); // not really an explicit position + } } break; } @@ -1229,7 +1252,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) S60->avkonComponentsSupportTransparency = (value==1) ? true : false; } } -#endif +#endif if (touch) { QApplicationPrivate::navigationMode = Qt::NavigationModeNone; @@ -1450,6 +1473,9 @@ void QApplicationPrivate::closePopup(QWidget *popup) QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget() : q_func()->focusWidget(); if (fw) { + if(fw->window()->isModal()) // restore pointer capture for modal window + fw->effectiveWinId()->SetPointerCapture(true); + if (fw != q_func()->focusWidget()) { fw->setFocus(Qt::PopupFocusReason); } else { diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 131b9bb..9872514 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -115,6 +115,8 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c # include <winable.h> #endif +#include "private/qwinnativepangesturerecognizer_win_p.h" + #ifndef WM_TOUCH # define WM_TOUCH 0x0240 @@ -2524,6 +2526,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } result = false; break; +#if !defined(Q_WS_WINCE) || defined(QT_WINCE_GESTURES) case WM_GESTURE: { GESTUREINFO gi; memset(&gi, 0, sizeof(GESTUREINFO)); @@ -2556,6 +2559,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam result = true; break; } +#endif // !defined(Q_WS_WINCE) || defined(QT_WINCE_GESTURES) #ifndef QT_NO_CURSOR case WM_SETCURSOR: { QCursor *ovr = QApplication::overrideCursor(); @@ -4012,12 +4016,45 @@ void QSessionManager::cancel() #endif //QT_NO_SESSIONMANAGER +bool QApplicationPrivate::HasTouchSupport = false; PtrRegisterTouchWindow QApplicationPrivate::RegisterTouchWindow = 0; PtrGetTouchInputInfo QApplicationPrivate::GetTouchInputInfo = 0; PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0; void QApplicationPrivate::initializeMultitouch_sys() { + static const IID QT_IID_IInkTablets = {0x112086D9, 0x7779, 0x4535, {0xA6, 0x99, 0x86, 0x2B, 0x43, 0xAC, 0x18, 0x63} }; + static const IID QT_IID_IInkTablet2 = {0x90c91ad2, 0xfa36, 0x49d6, {0x95, 0x16, 0xce, 0x8d, 0x57, 0x0f, 0x6f, 0x85} }; + static const CLSID QT_CLSID_InkTablets = {0x6E4FCB12, 0x510A, 0x4d40, {0x93, 0x04, 0x1D, 0xA1, 0x0A, 0xE9, 0x14, 0x7C} }; + + IInkTablets *iInkTablets = 0; + HRESULT hr = CoCreateInstance(QT_CLSID_InkTablets, NULL, CLSCTX_ALL, QT_IID_IInkTablets, (void**)&iInkTablets); + if (SUCCEEDED(hr)) { + long count = 0; + iInkTablets->get_Count(&count); + for (long i = 0; i < count; ++i) { + IInkTablet *iInkTablet = 0; + hr = iInkTablets->Item(i, &iInkTablet); + if (FAILED(hr)) + continue; + IInkTablet2 *iInkTablet2 = 0; + hr = iInkTablet->QueryInterface(QT_IID_IInkTablet2, (void**)&iInkTablet2); + iInkTablet->Release(); + if (FAILED(hr)) + continue; + TabletDeviceKind kind; + hr = iInkTablet2->get_DeviceKind(&kind); + iInkTablet2->Release(); + if (FAILED(hr)) + continue; + if (kind == TDK_Touch) { + QApplicationPrivate::HasTouchSupport = true; + break; + } + } + iInkTablets->Release(); + } + QLibrary library(QLatin1String("user32")); // MinGW (g++ 3.4.5) accepts only C casts. RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow")); diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 3c2c743..20a7ff2 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -96,6 +96,11 @@ extern "C" { } #endif +#ifndef QT_GUI_DOUBLE_CLICK_RADIUS +#define QT_GUI_DOUBLE_CLICK_RADIUS 5 +#endif + + //#define ALIEN_DEBUG #if !defined(QT_NO_GLIB) @@ -312,9 +317,14 @@ static const char * x11_atomnames = { "_XEMBED\0" "_XEMBED_INFO\0" + // Wacom old. (before version 0.10) "Wacom Stylus\0" "Wacom Cursor\0" "Wacom Eraser\0" + + // Tablet + "STYLUS\0" + "ERASER\0" }; Q_GUI_EXPORT QX11Data *qt_x11Data = 0; @@ -2340,12 +2350,12 @@ void qt_init(QApplicationPrivate *priv, int, gotStylus = true; } #else - if (devs->type == ATOM(XWacomStylus)) { + if (devs->type == ATOM(XWacomStylus) || devs->type == ATOM(XTabletStylus)) { deviceType = QTabletEvent::Stylus; if (wacomDeviceName()->isEmpty()) wacomDeviceName()->append(devs->name); gotStylus = true; - } else if (devs->type == ATOM(XWacomEraser)) { + } else if (devs->type == ATOM(XWacomEraser) || devs->type == ATOM(XTabletEraser)) { deviceType = QTabletEvent::XFreeEraser; gotEraser = true; } @@ -4194,8 +4204,8 @@ bool QETWidget::translateMouseEvent(const XEvent *event) mouseButtonPressed == button && (long)event->xbutton.time -(long)mouseButtonPressTime < QApplication::doubleClickInterval() && - qAbs(event->xbutton.x - mouseXPos) < 5 && - qAbs(event->xbutton.y - mouseYPos) < 5) { + qAbs(event->xbutton.x - mouseXPos) < QT_GUI_DOUBLE_CLICK_RADIUS && + qAbs(event->xbutton.y - mouseYPos) < QT_GUI_DOUBLE_CLICK_RADIUS) { type = QEvent::MouseButtonDblClick; mouseButtonPressTime -= 2000; // no double-click next time } else { diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 89ad94d..aa6720e 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -45,6 +45,7 @@ #include "private/qgesture_p.h" #include "private/qgraphicsitem_p.h" #include "private/qevent_p.h" +#include "private/qapplication_p.h" #include "qgesture.h" #include "qevent.h" #include "qgraphicsitem.h" @@ -86,7 +87,8 @@ QGestureManager::QGestureManager(QObject *parent) #endif #if defined(Q_OS_WIN) #if !defined(QT_NO_NATIVE_GESTURES) - registerGestureRecognizer(new QWinNativePanGestureRecognizer); + if (QApplicationPrivate::HasTouchSupport) + registerGestureRecognizer(new QWinNativePanGestureRecognizer); #endif #else registerGestureRecognizer(new QTapAndHoldGestureRecognizer); diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index ac4cdc8..f5004b0 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -278,7 +278,14 @@ int qt_wince_get_version() bool qt_wince_is_windows_mobile_65() { - return ((qt_wince_get_version() == 52) && (qt_wince_get_build() > 2000)); + const DWORD dwFirstWM65BuildNumber = 21139; + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(osvi); + if (!GetVersionEx(&osvi)) + return false; + return osvi.dwMajorVersion > 5 + || (osvi.dwMajorVersion == 5 && (osvi.dwMinorVersion > 2 || + (osvi.dwMinorVersion == 2 && osvi.dwBuildNumber >= dwFirstWM65BuildNumber))); } bool qt_wince_is_pocket_pc() { diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp index 4e6c847..b32b626 100644 --- a/src/gui/kernel/qkeymapper_x11.cpp +++ b/src/gui/kernel/qkeymapper_x11.cpp @@ -1073,8 +1073,8 @@ static const unsigned int KeyTbl[] = { XF86XK_AudioNext, Qt::Key_MediaNext, XF86XK_AudioRecord, Qt::Key_MediaRecord, XF86XK_Mail, Qt::Key_LaunchMail, - XF86XK_MyComputer, Qt::Key_Launch0, - XF86XK_Calculator, Qt::Key_Calculator, + XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 5: remap properly + XF86XK_Calculator, Qt::Key_Launch1, XF86XK_Memo, Qt::Key_Memo, XF86XK_ToDoList, Qt::Key_ToDoList, XF86XK_Calendar, Qt::Key_Calendar, @@ -1172,7 +1172,7 @@ static const unsigned int KeyTbl[] = { XF86XK_Bluetooth, Qt::Key_Bluetooth, XF86XK_Suspend, Qt::Key_Suspend, XF86XK_Hibernate, Qt::Key_Hibernate, - XF86XK_Launch0, Qt::Key_Launch2, + XF86XK_Launch0, Qt::Key_Launch2, // ### Qt 5: remap properly XF86XK_Launch1, Qt::Key_Launch3, XF86XK_Launch2, Qt::Key_Launch4, XF86XK_Launch3, Qt::Key_Launch5, diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp index e191d7b..39633bf 100644 --- a/src/gui/kernel/qmime_win.cpp +++ b/src/gui/kernel/qmime_win.cpp @@ -640,14 +640,18 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat } else if (getCf(formatetc) == CF_INETURL_W) { QList<QUrl> urls = mimeData->urls(); QByteArray result; - QString url = urls.at(0).toString(); - result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort)); + if (!urls.isEmpty()) { + QString url = urls.at(0).toString(); + result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort)); + } result.append('\0'); result.append('\0'); return setData(result, pmedium); } else if (getCf(formatetc) == CF_INETURL) { QList<QUrl> urls = mimeData->urls(); - QByteArray result = urls.at(0).toString().toLocal8Bit(); + QByteArray result; + if (!urls.isEmpty()) + result = urls.at(0).toString().toLocal8Bit(); return setData(result, pmedium); } } diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp index 8ac1e31..3a0304c 100644 --- a/src/gui/kernel/qsoftkeymanager_s60.cpp +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -60,7 +60,7 @@ const int LSK_POSITION = 0; const int MSK_POSITION = 3; const int RSK_POSITION = 2; -QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60() +QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60() : cbaHasImage(4) // 4 since MSK position index is 3 { cachedCbaIconSize[0] = QSize(0,0); cachedCbaIconSize[1] = QSize(0,0); @@ -73,11 +73,21 @@ bool QSoftKeyManagerPrivateS60::skipCbaUpdate() // Lets not update softkeys if // 1. We don't have application panes, i.e. cba // 2. Our CBA is not active, i.e. S60 native dialog or menu with custom CBA is shown + // 2.1. Except if thre is no current CBA at all and WindowSoftkeysRespondHint is set + // Note: Cannot use IsDisplayingMenuOrDialog since CBA update can be triggered before // menu/dialog CBA is actually displayed i.e. it is being costructed. CEikButtonGroupContainer *appUiCba = S60->buttonGroupContainer(); + // CEikButtonGroupContainer::Current returns 0 if CBA is not visible at all CEikButtonGroupContainer *currentCba = CEikButtonGroupContainer::Current(); - if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) || appUiCba != currentCba) { + // Check if softkey need to be update even they are not visible + bool cbaRespondsWhenInvisible = false; + QWidget *window = QApplication::activeWindow(); + if (window && (window->windowFlags() & Qt::WindowSoftkeysRespondHint)) + cbaRespondsWhenInvisible = true; + + if (QApplication::testAttribute(Qt::AA_S60DontConstructApplicationPanes) + || (appUiCba != currentCba && !cbaRespondsWhenInvisible)) { return true; } return false; @@ -255,10 +265,14 @@ bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba, myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transfered EikSoftkeyImage::SetImage(cba, *myimage, left); // Takes myimage ownership + cbaHasImage[position] = true; ret = true; } else { // Restore softkey to text based - EikSoftkeyImage::SetLabel(cba, left); + if (cbaHasImage[position]) { + EikSoftkeyImage::SetLabel(cba, left); + cbaHasImage[position] = false; + } } } return ret; @@ -274,7 +288,12 @@ bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba, TPtrC nativeText = qt_QString2TPtrC(text); int command = S60_COMMAND_START + position; setNativeSoftkey(cba, position, command, nativeText); - cba.DimCommand(command, !action->isEnabled()); + // QMainWindow "Options" action is set to invisible in order it does not appear in context menu + // and all invisible actions are by default disabled. + // However we never want to dim options softkey, even it is set to invisible + QVariant property = action->property(MENU_ACTION_PROPERTY); + const bool dimmed = (property.isValid() && property.toBool()) ? false : !action->isEnabled(); + cba.DimCommand(command, dimmed); realSoftKeyActions.insert(command, action); return true; } @@ -311,7 +330,10 @@ bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba) if (windowType != Qt::Dialog && windowType != Qt::Popup) { QString text(QSoftKeyManager::tr("Exit")); TPtrC nativeText = qt_QString2TPtrC(text); - EikSoftkeyImage::SetLabel(&cba, false); + if (cbaHasImage[RSK_POSITION]) { + EikSoftkeyImage::SetLabel(&cba, false); + cbaHasImage[RSK_POSITION] = false; + } setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText); return true; } diff --git a/src/gui/kernel/qsoftkeymanager_s60_p.h b/src/gui/kernel/qsoftkeymanager_s60_p.h index 823a2db..a5e5016 100644 --- a/src/gui/kernel/qsoftkeymanager_s60_p.h +++ b/src/gui/kernel/qsoftkeymanager_s60_p.h @@ -53,6 +53,7 @@ // We mean it. // +#include "qbitarray.h" #include "private/qobject_p.h" #include "private/qsoftkeymanager_common_p.h" @@ -98,6 +99,7 @@ private: private: QHash<int, QAction*> realSoftKeyActions; QSize cachedCbaIconSize[4]; + QBitArray cbaHasImage; }; diff --git a/src/gui/kernel/qsound_mac.mm b/src/gui/kernel/qsound_mac.mm index 61e42ba..71fd663 100644 --- a/src/gui/kernel/qsound_mac.mm +++ b/src/gui/kernel/qsound_mac.mm @@ -174,6 +174,7 @@ NSSound *QAuServerMac::createNSSound(const QString &fileName, QSound *qSound) NSSound * const nsSound = [[NSSound alloc] initWithContentsOfFile: nsFileName byReference:YES]; QMacSoundDelegate * const delegate = [[QMacSoundDelegate alloc] initWithQSound:qSound:this]; [nsSound setDelegate:delegate]; + [nsFileName release]; return nsSound; } diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index 167557b..8af4df5 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -672,6 +672,9 @@ struct QX11Data XWacomCursor, XWacomEraser, + XTabletStylus, + XTabletEraser, + NPredefinedAtoms, _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms, diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index ed9d5de..e5310ea 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -7583,6 +7583,23 @@ void QWidgetPrivate::hideChildren(bool spontaneous) QWidget *widget = qobject_cast<QWidget*>(childList.at(i)); if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden)) continue; +#ifdef QT_MAC_USE_COCOA + // Before doing anything we need to make sure that we don't leave anything in a non-consistent state. + // When hiding a widget we need to make sure that no mouse_down events are active, because + // the mouse_up event will never be received by a hidden widget or one of its descendants. + // The solution is simple, before going through with this we check if there are any mouse_down events in + // progress, if so we check if it is related to this widget or not. If so, we just reset the mouse_down and + // then we continue. + // In X11 and Windows we send a mouse_release event, however we don't do that here because we were already + // ignoring that from before. I.e. Carbon did not send the mouse release event, so we will not send the + // mouse release event. There are two ways to interpret this: + // 1. If we don't send the mouse release event, the widget might get into an inconsistent state, i.e. it + // might be waiting for a release event that will never arrive. + // 2. If we send the mouse release event, then the widget might decide to trigger an action that is not + // supposed to trigger because it is not visible. + if(widget == qt_button_down) + qt_button_down = 0; +#endif // QT_MAC_USE_COCOA if (spontaneous) widget->setAttribute(Qt::WA_Mapped, false); else @@ -7975,13 +7992,16 @@ inline void setDisabledStyle(QWidget *w, bool setStyle) // set/reset WS_DISABLED style. if(w && w->isWindow() && w->isVisible() && w->isEnabled()) { LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE); + LONG newStyle = dwStyle; if (setStyle) - dwStyle |= WS_DISABLED; + newStyle |= WS_DISABLED; else - dwStyle &= ~WS_DISABLED; - SetWindowLong(w->winId(), GWL_STYLE, dwStyle); - // we might need to repaint in some situations (eg. menu) - w->repaint(); + newStyle &= ~WS_DISABLED; + if (newStyle != dwStyle) { + SetWindowLong(w->winId(), GWL_STYLE, newStyle); + // we might need to repaint in some situations (eg. menu) + w->repaint(); + } } } #endif diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 6d8c97b..5889589 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -152,6 +152,7 @@ static bool qt_mac_raise_process = true; static OSWindowRef qt_root_win = 0; QWidget *mac_mouse_grabber = 0; QWidget *mac_keyboard_grabber = 0; +extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp #ifndef QT_MAC_USE_COCOA #ifdef QT_NAMESPACE @@ -872,7 +873,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, & ~Qt::WindowMaximized)); QApplication::sendSpontaneousEvent(widget, &e); } - extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp qt_button_down = 0; } else if(ekind == kEventWindowCollapsed) { if (!widget->isMinimized()) { @@ -900,7 +900,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, //we send a hide to be like X11/Windows QEvent e(QEvent::Hide); QApplication::sendSpontaneousEvent(widget, &e); - extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp qt_button_down = 0; } else if(ekind == kEventWindowToolbarSwitchMode) { macSendToolbarChangeEvent(widget); @@ -1274,6 +1273,11 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, if (widget->isVisible() && widget->updatesEnabled()) { //process the actual paint event. if(widget->testAttribute(Qt::WA_WState_InPaintEvent)) qWarning("QWidget::repaint: Recursive repaint detected"); + if (widget->isWindow() && !widget->d_func()->isOpaque + && !widget->testAttribute(Qt::WA_MacBrushedMetal)) { + QRect qrgnRect = qrgn.boundingRect(); + CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height())); + } QPoint redirectionOffset(0, 0); QWidget *tl = widget->window(); @@ -1324,13 +1328,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, widget->d_func()->restoreRedirected(); } - if (widget->isWindow() && !widget->d_func()->isOpaque - && !widget->testAttribute(Qt::WA_MacBrushedMetal)) { - QRect qrgnRect = qrgn.boundingRect(); - CGContextClearRect(cg, CGRectMake(qrgnRect.x(), qrgnRect.y(), qrgnRect.width(), qrgnRect.height())); - } - - if(!HIObjectIsOfClass((HIObjectRef)hiview, kObjectQWidget)) CallNextEventHandler(er, event); @@ -1527,7 +1524,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, if (widget) { qt_event_request_window_change(widget); if (!HIViewIsVisible(HIViewRef(widget->winId()))) { - extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp if (widget == qt_button_down) qt_button_down = 0; } @@ -1536,7 +1532,6 @@ OSStatus QWidgetPrivate::qt_widget_event(EventHandlerCallRef er, EventRef event, break; } case kEventClassMouse: { bool send_to_app = false; - extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp if(qt_button_down) send_to_app = true; if(send_to_app) { @@ -3493,7 +3488,6 @@ void QWidgetPrivate::hide_sys() Q_Q(QWidget); if((q->windowType() == Qt::Desktop)) //you can't hide the desktop! return; - QMacCocoaAutoReleasePool pool; if(q->isWindow()) { #ifdef QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index ebd289c..7fb21d2 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1042,7 +1042,13 @@ void QWidget::setWindowState(Qt::WindowStates newstate) Q_D(QWidget); Qt::WindowStates oldstate = windowState(); - if (oldstate == newstate) + + const TBool isFullscreen = newstate & Qt::WindowFullScreen; + const TBool cbaRequested = windowFlags() & Qt::WindowSoftkeysVisibleHint; + const TBool cbaVisible = CEikButtonGroupContainer::Current() ? true : false; + const TBool softkeyVisibilityChange = isFullscreen && (cbaRequested != cbaVisible); + + if (oldstate == newstate && !softkeyVisibilityChange) return; if (isWindow()) { @@ -1058,16 +1064,27 @@ void QWidget::setWindowState(Qt::WindowStates newstate) #ifdef Q_WS_S60 // Hide window decoration when switching to fullsccreen / minimized otherwise show decoration. - // The window decoration visibility has to be changed before doing actual window state - // change since in that order the availableGeometry will return directly the right size and + // The window decoration visibility has to be changed before doing actual window state + // change since in that order the availableGeometry will return directly the right size and // we will avoid unnecessarty redraws - CEikStatusPane* statusPane = S60->statusPane(); - CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); - TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); + CEikStatusPane *statusPane = S60->statusPane(); + CEikButtonGroupContainer *buttonGroup = S60->buttonGroupContainer(); + TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); if (statusPane) statusPane->MakeVisible(visible); - if (buttonGroup) - buttonGroup->MakeVisible(visible); + if (buttonGroup) { + // Visibility + buttonGroup->MakeVisible(visible || (isFullscreen && cbaRequested)); + + // Responsiviness + CEikCba *cba = static_cast<CEikCba *>( buttonGroup->ButtonGroup() ); // downcast from MEikButtonGroup + TUint cbaFlags = cba->ButtonGroupFlags(); + if(windowFlags() & Qt::WindowSoftkeysRespondHint) + cbaFlags |= EAknCBAFlagRespondWhenInvisible; + else + cbaFlags &= ~EAknCBAFlagRespondWhenInvisible; + cba->SetButtonGroupFlags(cbaFlags); + } #endif // Q_WS_S60 createWinId(); @@ -1080,7 +1097,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry; if (newstate & Qt::WindowFullScreen) - setGeometry(qApp->desktop()->screenGeometry(this)); + setGeometry(qApp->desktop()->availableGeometry(this)); else if (newstate & Qt::WindowMaximized) setGeometry(qApp->desktop()->availableGeometry(this)); else @@ -1220,8 +1237,10 @@ void QWidget::releaseMouse() { if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) { Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - WId id = effectiveWinId(); - id->SetPointerCapture(false); + if(!window()->isModal()) { + WId id = effectiveWinId(); + id->SetPointerCapture(false); + } QWidgetPrivate::mouseGrabber = 0; #ifndef QT_NO_CURSOR QApplication::restoreOverrideCursor(); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 8cab387..2dcbfc3 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -2073,6 +2073,8 @@ void QWidgetPrivate::winSetupGestures() if (!q || !q->isVisible() || !nativeGesturePanEnabled) return; + if (!QApplicationPrivate::HasTouchSupport) + return; QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); if (!qAppPriv->SetGestureConfig) return; diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h index c65fa50..146b067 100644 --- a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h +++ b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h @@ -54,6 +54,38 @@ // #include <QGestureRecognizer> +#include <objbase.h> + +class IInkRectangle; +class TabletHardwareCapabilities; +class TabletPropertyMetricUnit; +DECLARE_INTERFACE_(IInkTablet, IDispatch) +{ + STDMETHOD(get_Name)(THIS_ BSTR *Name) PURE; + STDMETHOD(get_PlugAndPlayId)(THIS_ BSTR *Id) PURE; + STDMETHOD(get_MaximumInputRectangle)(THIS_ IInkRectangle **Rectangle) PURE; + STDMETHOD(get_HardwareCapabilities)(THIS_ TabletHardwareCapabilities *Capabilities) PURE; + STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName) PURE; + STDMETHOD(GetPropertyMetrics)(THIS_ BSTR propertyName, long *Minimum, long *Maximum, TabletPropertyMetricUnit *Units, float *Resolution) PURE; +}; +enum TabletDeviceKind +{ + TDK_Mouse = 0, + TDK_Pen = 1, + TDK_Touch = 2 +}; +DECLARE_INTERFACE_(IInkTablet2, IDispatch) +{ + STDMETHOD(get_DeviceKind)(THIS_ TabletDeviceKind *Kind) PURE; +}; +DECLARE_INTERFACE_(IInkTablets, IDispatch) +{ + STDMETHOD(get_Count)(THIS_ long *Count) PURE; + STDMETHOD(get__NewEnum)(THIS_ IUnknown **_NewEnum) PURE; + STDMETHOD(get_DefaultTablet)(THIS_ IInkTablet **DefaultTablet) PURE; + STDMETHOD(Item)(THIS_ long Index, IInkTablet **Tablet) PURE; + STDMETHOD(IsPacketPropertySupported)(THIS_ BSTR packetPropertyName, VARIANT_BOOL *Supported) PURE; +}; QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index c73d9f4..8de9eaa 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -352,6 +352,10 @@ void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QWindowS // Always flush repainted areas. dirtyOnScreen += toClean; +#ifdef Q_WS_QWS + toClean.translate(tlwOffset); +#endif + #ifdef QT_NO_PAINT_DEBUG windowSurface->beginPaint(toClean); #else @@ -766,7 +770,12 @@ void QWidgetBackingStore::paintWindowDecoration() if (decorationRegion.isEmpty()) return; - windowSurface->beginPaint(decorationRegion); + //### The QWS decorations do not always paint the pixels they promise to paint. + // This causes painting problems with QWSMemorySurface. Since none of the other + // window surfaces actually use the region, passing an empty region is a safe + // workaround. + + windowSurface->beginPaint(QRegion()); QPaintEngine *engine = windowSurface->paintDevice()->paintEngine(); Q_ASSERT(engine); diff --git a/src/gui/painting/qgraphicssystem_raster.cpp b/src/gui/painting/qgraphicssystem_raster.cpp index f90aea0..909508e 100644 --- a/src/gui/painting/qgraphicssystem_raster.cpp +++ b/src/gui/painting/qgraphicssystem_raster.cpp @@ -41,19 +41,32 @@ #include "qgraphicssystem_raster_p.h" +#ifdef Q_OS_SYMBIAN +#include "private/qpixmap_s60_p.h" +#include "private/qwindowsurface_s60_p.h" +#else #include "private/qpixmap_raster_p.h" #include "private/qwindowsurface_raster_p.h" +#endif QT_BEGIN_NAMESPACE QPixmapData *QRasterGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const { +#ifdef Q_OS_SYMBIAN + return new QS60PixmapData(type); +#else return new QRasterPixmapData(type); +#endif } QWindowSurface *QRasterGraphicsSystem::createWindowSurface(QWidget *widget) const { +#ifdef Q_OS_SYMBIAN + return new QS60WindowSurface(widget); +#else return new QRasterWindowSurface(widget); +#endif } QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_qws.cpp b/src/gui/painting/qwindowsurface_qws.cpp index d3fc9de..a816ed2 100644 --- a/src/gui/painting/qwindowsurface_qws.cpp +++ b/src/gui/painting/qwindowsurface_qws.cpp @@ -80,7 +80,7 @@ static void qt_insertWindowSurface(int winId, QWSWindowSurface *surface) inline bool isWidgetOpaque(const QWidget *w) { - return w->d_func()->isOpaque; + return w->d_func()->isOpaque && !w->testAttribute(Qt::WA_TranslucentBackground); } static inline QScreen *getScreen(const QWidget *w) @@ -873,6 +873,21 @@ bool QWSMemorySurface::isValid() const return true; } +// ### copied from qwindowsurface_raster.cpp -- should be cross-platform +void QWSMemorySurface::beginPaint(const QRegion &rgn) +{ + if (!isWidgetOpaque(window())) { + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + const QVector<QRect> rects = rgn.rects(); + const QColor blank = Qt::transparent; + for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { + p.fillRect(*it, blank); + } + } + QWSWindowSurface::beginPaint(rgn); +} + // from qwindowsurface.cpp extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); diff --git a/src/gui/painting/qwindowsurface_qws_p.h b/src/gui/painting/qwindowsurface_qws_p.h index a8371c8..30900dc 100644 --- a/src/gui/painting/qwindowsurface_qws_p.h +++ b/src/gui/painting/qwindowsurface_qws_p.h @@ -176,6 +176,8 @@ public: QImage image() const { return img; } QPoint painterOffset() const; + void beginPaint(const QRegion &rgn); + bool lock(int timeout = -1); void unlock(); diff --git a/src/gui/styles/qgtkstyle_p.cpp b/src/gui/styles/qgtkstyle_p.cpp index 6916c02..3c6a1ef 100644 --- a/src/gui/styles/qgtkstyle_p.cpp +++ b/src/gui/styles/qgtkstyle_p.cpp @@ -92,8 +92,8 @@ Ptr_gtk_widget_set_default_direction QGtkStylePrivate::gtk_widget_set_default_di Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_fg = 0; Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_bg = 0; Ptr_gtk_arrow_new QGtkStylePrivate::gtk_arrow_new = 0; -Ptr_gtk_menu_item_new QGtkStylePrivate::gtk_menu_item_new = 0; -Ptr_gtk_check_menu_item_new QGtkStylePrivate::gtk_check_menu_item_new = 0; +Ptr_gtk_menu_item_new_with_label QGtkStylePrivate::gtk_menu_item_new_with_label = 0; +Ptr_gtk_check_menu_item_new_with_label QGtkStylePrivate::gtk_check_menu_item_new_with_label = 0; Ptr_gtk_menu_bar_new QGtkStylePrivate::gtk_menu_bar_new = 0; Ptr_gtk_menu_new QGtkStylePrivate::gtk_menu_new = 0; Ptr_gtk_button_new QGtkStylePrivate::gtk_button_new = 0; @@ -354,8 +354,8 @@ void QGtkStylePrivate::resolveGtk() const gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_fg"); gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_bg"); gtk_arrow_new = (Ptr_gtk_arrow_new)libgtk.resolve("gtk_arrow_new"); - gtk_menu_item_new = (Ptr_gtk_menu_item_new)libgtk.resolve("gtk_menu_item_new"); - gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)libgtk.resolve("gtk_check_menu_item_new"); + gtk_menu_item_new_with_label = (Ptr_gtk_menu_item_new_with_label)libgtk.resolve("gtk_menu_item_new_with_label"); + gtk_check_menu_item_new_with_label = (Ptr_gtk_check_menu_item_new_with_label)libgtk.resolve("gtk_check_menu_item_new_with_label"); gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)libgtk.resolve("gtk_menu_bar_new"); gtk_menu_new = (Ptr_gtk_menu_new)libgtk.resolve("gtk_menu_new"); gtk_toolbar_new = (Ptr_gtk_toolbar_new)libgtk.resolve("gtk_toolbar_new"); @@ -446,7 +446,7 @@ void QGtkStylePrivate::initGtkMenu() const GtkWidget *gtkMenuBar = QGtkStylePrivate::gtk_menu_bar_new(); setupGtkWidget(gtkMenuBar); - GtkWidget *gtkMenuBarItem = QGtkStylePrivate::gtk_menu_item_new(); + GtkWidget *gtkMenuBarItem = QGtkStylePrivate::gtk_menu_item_new_with_label("X"); gtk_menu_shell_append((GtkMenuShell*)(gtkMenuBar), gtkMenuBarItem); gtk_widget_realize(gtkMenuBarItem); @@ -455,14 +455,11 @@ void QGtkStylePrivate::initGtkMenu() const gtk_menu_item_set_submenu((GtkMenuItem*)(gtkMenuBarItem), gtkMenu); gtk_widget_realize(gtkMenu); - GtkWidget *gtkMenuItem = QGtkStylePrivate::gtk_menu_item_new(); - g_object_set(gtkMenuItem, "label", "X", NULL); - + GtkWidget *gtkMenuItem = QGtkStylePrivate::gtk_menu_item_new_with_label("X"); gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuItem); gtk_widget_realize(gtkMenuItem); - GtkWidget *gtkCheckMenuItem = QGtkStylePrivate::gtk_check_menu_item_new(); - g_object_set(gtkCheckMenuItem, "label", "X", NULL); + GtkWidget *gtkCheckMenuItem = QGtkStylePrivate::gtk_check_menu_item_new_with_label("X"); gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkCheckMenuItem); gtk_widget_realize(gtkCheckMenuItem); @@ -540,7 +537,7 @@ void QGtkStylePrivate::initGtkWidgets() const GtkWidget *gtkButton = QGtkStylePrivate::gtk_button_new(); addWidget(gtkButton); g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), 0); - addWidget(QGtkStylePrivate::gtk_tool_button_new(NULL, NULL)); + addWidget(QGtkStylePrivate::gtk_tool_button_new(NULL, "Qt")); addWidget(QGtkStylePrivate::gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)); addWidget(QGtkStylePrivate::gtk_hbutton_box_new()); addWidget(QGtkStylePrivate::gtk_check_button_new()); diff --git a/src/gui/styles/qgtkstyle_p.h b/src/gui/styles/qgtkstyle_p.h index 6ee7904..5bb7550 100644 --- a/src/gui/styles/qgtkstyle_p.h +++ b/src/gui/styles/qgtkstyle_p.h @@ -139,9 +139,9 @@ typedef void (*Ptr_gtk_widget_realize) (GtkWidget *); typedef void (*Ptr_gtk_widget_set_default_direction) (GtkTextDirection); typedef void (*Ptr_gtk_widget_modify_color)(GtkWidget *widget, GtkStateType state, const GdkColor *color); typedef GtkWidget* (*Ptr_gtk_arrow_new)(GtkArrowType, GtkShadowType); -typedef GtkWidget* (*Ptr_gtk_menu_item_new)(void); +typedef GtkWidget* (*Ptr_gtk_menu_item_new_with_label)(const gchar *); typedef GtkWidget* (*Ptr_gtk_separator_menu_item_new)(void); -typedef GtkWidget* (*Ptr_gtk_check_menu_item_new)(void); +typedef GtkWidget* (*Ptr_gtk_check_menu_item_new_with_label)(const gchar *); typedef GtkWidget* (*Ptr_gtk_menu_bar_new)(void); typedef GtkWidget* (*Ptr_gtk_menu_new)(void); typedef GtkWidget* (*Ptr_gtk_combo_box_entry_new)(void); @@ -357,9 +357,9 @@ public: static Ptr_gtk_widget_set_default_direction gtk_widget_set_default_direction; static Ptr_gtk_widget_modify_color gtk_widget_modify_fg; static Ptr_gtk_widget_modify_color gtk_widget_modify_bg; - static Ptr_gtk_menu_item_new gtk_menu_item_new; + static Ptr_gtk_menu_item_new_with_label gtk_menu_item_new_with_label; static Ptr_gtk_arrow_new gtk_arrow_new; - static Ptr_gtk_check_menu_item_new gtk_check_menu_item_new; + static Ptr_gtk_check_menu_item_new_with_label gtk_check_menu_item_new_with_label; static Ptr_gtk_menu_bar_new gtk_menu_bar_new; static Ptr_gtk_menu_new gtk_menu_new; static Ptr_gtk_expander_new gtk_expander_new; diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 565cc2c..bf5a62e 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -759,13 +759,29 @@ void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const QApplication::setPalette(widgetPalette, "QMenuBar"); widgetPalette = *palette; + widgetPalette.setColor(QPalette::Text, + s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); + QApplication::setPalette(widgetPalette, "QMenu"); + widgetPalette = *palette; + widgetPalette.setColor(QPalette::WindowText, s60Color(QS60StyleEnums::CL_QsnTextColors, 4, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 3, 0)); QApplication::setPalette(widgetPalette, "QTabBar"); widgetPalette = *palette; + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0)); + QApplication::setPalette(widgetPalette, "QListView"); + widgetPalette = *palette; + widgetPalette.setColor(QPalette::Text, s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); QApplication::setPalette(widgetPalette, "QTableView"); widgetPalette = *palette; @@ -789,6 +805,8 @@ void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const widgetPalette = *palette; widgetPalette.setColor(QPalette::WindowText, s60Color(QS60StyleEnums::CL_QsnTextColors, 7, 0)); + widgetPalette.setColor(QPalette::HighlightedText, + s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); QApplication::setPalette(widgetPalette, "QRadioButton"); QApplication::setPalette(widgetPalette, "QCheckBox"); widgetPalette = *palette; @@ -1241,6 +1259,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, case CE_RadioButton: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { bool isRadio = (element == CE_RadioButton); + QStyleOptionButton subopt = *btn; + // Highlight needs to be drawn first, as it goes "underneath" the text and indicator. if (btn->state & State_HasFocus) { QStyleOptionFocusRect fropt; @@ -1248,8 +1268,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect : SE_CheckBoxFocusRect, btn, widget); drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + + subopt.palette.setColor(QPalette::Active, QPalette::WindowText, + subopt.palette.highlightedText().color()); } - QStyleOptionButton subopt = *btn; subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator : SE_CheckBoxIndicator, btn, widget); @@ -1408,7 +1430,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);} // draw the focus rect - if (isSelected | hasFocus) { + if (isSelected || hasFocus ) { QRect highlightRect = option->rect.adjusted(1,1,-1,-1); QAbstractItemView::SelectionBehavior selectionBehavior = itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems; @@ -1480,15 +1502,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, // draw the text if (!voptAdj.text.isEmpty()) { - if (isSelected) { - if (qobject_cast<const QTableView *>(widget)) - voptAdj.palette.setColor( - QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); - else - voptAdj.palette.setColor( - QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0)); - } - painter->setPen(voptAdj.palette.text().color()); + if (isSelected || hasFocus ) + painter->setPen(voptAdj.palette.highlightedText().color()); + else + painter->setPen(voptAdj.palette.text().color()); d->viewItemDrawText(painter, &voptAdj, textRect); } painter->restore(); @@ -1590,7 +1607,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, const bool selected = optionTab.state & State_Selected; if (selected) optionTab.palette.setColor(QPalette::Active, QPalette::WindowText, - QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 3, option)); + optionTab.palette.highlightedText().color()); const bool verticalTabs = optionTab.shape == QTabBar::RoundedEast || optionTab.shape == QTabBar::RoundedWest @@ -1723,7 +1740,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, if (!styleHint(SH_UnderlineShortcut, menuItem, widget)) text_flags |= Qt::TextHideMnemonic; - if ((option->state & State_Selected) && (option->state & State_Enabled)) + const bool selected = (option->state & State_Selected) && (option->state & State_Enabled); + if (selected) QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags); QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget); @@ -1793,6 +1811,10 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, painter->save(); painter->setOpacity(0.5); } + if (selected) + optionMenuItem.palette.setColor( + QPalette::Active, QPalette::Text, optionMenuItem.palette.highlightedText().color()); + QCommonStyle::drawItemText(painter, textRect, text_flags, optionMenuItem.palette, enabled, optionMenuItem.text, QPalette::Text); diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp index a264b1b..6e77409 100644 --- a/src/gui/styles/qwindowsmobilestyle.cpp +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -4040,25 +4040,26 @@ enum QSliderDirection { SliderUp, SliderDown, SliderLeft, SliderRight }; void QWindowsMobileStylePrivate::tintImagesButton(QColor color) { - if (currentTintButton == color) + if (currentTintButton == color) return; - - imageTabEnd = QImage(tabend_xpm); - imageTabSelectedEnd = QImage(tabselectedend_xpm); - imageTabSelectedBegin = QImage(tabselectedbeginn_xpm); - imageTabMiddle = QImage(tabmiddle_xpm); - tintImage(&imageTabEnd, color, 0.0); - tintImage(&imageTabSelectedEnd, color, 0.0); - tintImage(&imageTabSelectedBegin, color, 0.0); - tintImage(&imageTabMiddle, color, 0.0); - - if (!doubleControls) { - int height = imageTabMiddle.height() / 2 + 1; - imageTabEnd = imageTabEnd.scaledToHeight(height); - imageTabMiddle = imageTabMiddle.scaledToHeight(height); - imageTabSelectedEnd = imageTabSelectedEnd.scaledToHeight(height); - imageTabSelectedBegin = imageTabSelectedBegin.scaledToHeight(height); - } + currentTintButton = color; + + imageTabEnd = QImage(tabend_xpm); + imageTabSelectedEnd = QImage(tabselectedend_xpm); + imageTabSelectedBegin = QImage(tabselectedbeginn_xpm); + imageTabMiddle = QImage(tabmiddle_xpm); + tintImage(&imageTabEnd, color, 0.0); + tintImage(&imageTabSelectedEnd, color, 0.0); + tintImage(&imageTabSelectedBegin, color, 0.0); + tintImage(&imageTabMiddle, color, 0.0); + + if (!doubleControls) { + int height = imageTabMiddle.height() / 2 + 1; + imageTabEnd = imageTabEnd.scaledToHeight(height); + imageTabMiddle = imageTabMiddle.scaledToHeight(height); + imageTabSelectedEnd = imageTabSelectedEnd.scaledToHeight(height); + imageTabSelectedBegin = imageTabSelectedBegin.scaledToHeight(height); + } } void QWindowsMobileStylePrivate::tintImagesHigh(QColor color) diff --git a/src/gui/util/qsystemtrayicon_mac.mm b/src/gui/util/qsystemtrayicon_mac.mm index 348657e..d943c8c 100644 --- a/src/gui/util/qsystemtrayicon_mac.mm +++ b/src/gui/util/qsystemtrayicon_mac.mm @@ -529,7 +529,11 @@ private: [item setToolTip:(NSString*)QCFString::toCFStringRef(action->toolTip())]; const QIcon icon = action->icon(); if(!icon.isNull()) { +#ifndef QT_MAC_USE_COCOA + const short scale = GetMBarHeight(); +#else const short scale = [[NSApp mainMenu] menuBarHeight]; +#endif NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(icon.pixmap(QSize(scale, scale)))); [item setImage: nsimage]; [nsimage release]; diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index bdab6fb..bf926f8 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -119,6 +119,7 @@ void QMainWindowPrivate::init() q->setAttribute(Qt::WA_Hover); #ifdef QT_SOFTKEYS_ENABLED menuBarAction = QSoftKeyManager::createAction(QSoftKeyManager::MenuSoftKey, q); + menuBarAction->setVisible(false); #endif } diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index d92168a..9527057 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -463,6 +463,8 @@ void QMainWindowLayout::removeFromMacToolbar(QToolBar *toolbar) NSToolbarItem *item = static_cast<NSToolbarItem *>(it.key()); [[qt_mac_window_for(layoutState.mainWindow->window()) toolbar] removeItemAtIndex:toolbarItemsCopy.indexOf(item)]; + unifiedToolbarHash.remove(item); + qtoolbarsInUnifiedToolbarList.removeAll(toolbar); #endif break; } diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp index eae97a6..e46688c 100644 --- a/src/gui/widgets/qmenu_symbian.cpp +++ b/src/gui/widgets/qmenu_symbian.cpp @@ -256,6 +256,14 @@ void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id) { SymbianMenuItem* menu = qt_symbian_find_menu(id, symbianMenus); if (menu) { + // Normally first AddMenuItemL call for menuPane will create the item array. + // However if we don't have any items, we still need the item array. Otherwise + // menupane will crash. That's why we create item array here manually, and + // AddMenuItemL will then use the existing array. + CEikMenuPane::CItemArray* itemArray = q_check_ptr(new CEikMenuPane::CItemArray); + menuPane->SetItemArray(itemArray); + menuPane->SetItemArrayOwnedExternally(EFalse); + for (int i = 0; i < menu->children.count(); ++i) QT_TRAP_THROWING(menuPane->AddMenuItemL(menu->children.at(i)->menuItemData)); } diff --git a/src/multimedia/audio/qaudioinput_mac_p.cpp b/src/multimedia/audio/qaudioinput_mac_p.cpp index 7251513..bd2de52 100644 --- a/src/multimedia/audio/qaudioinput_mac_p.cpp +++ b/src/multimedia/audio/qaudioinput_mac_p.cpp @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE -namespace +namespace QtMultimediaInternal { static const int default_buffer_size = 4 * 1024; @@ -169,8 +169,10 @@ public: void reset() { - for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i) + for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i) { bfs->mBuffers[i].mDataByteSize = dataSize; + bfs->mBuffers[i].mData = 0; + } } private: @@ -523,7 +525,7 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray& device, QAudioFormat co startTime = 0; totalFrames = 0; audioBuffer = 0; - internalBufferSize = default_buffer_size; + internalBufferSize = QtMultimediaInternal::default_buffer_size; clockFrequency = AudioGetHostClockFrequency() / 1000; errorCode = QAudio::NoError; stateCode = QAudio::StoppedState; @@ -668,13 +670,13 @@ bool QAudioInputPrivate::open() else internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame; - audioBuffer = new QAudioInputBuffer(internalBufferSize, + audioBuffer = new QtMultimediaInternal::QAudioInputBuffer(internalBufferSize, periodSizeBytes, deviceFormat, streamFormat, this); - audioIO = new MacInputDevice(audioBuffer, this); + audioIO = new QtMultimediaInternal::MacInputDevice(audioBuffer, this); // Init if (AudioUnitInitialize(audioUnit) != noErr) { diff --git a/src/multimedia/audio/qaudioinput_mac_p.h b/src/multimedia/audio/qaudioinput_mac_p.h index e1b8e4a..42f90e2 100644 --- a/src/multimedia/audio/qaudioinput_mac_p.h +++ b/src/multimedia/audio/qaudioinput_mac_p.h @@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE class QTimer; class QIODevice; -namespace +namespace QtMultimediaInternal { class QAudioInputBuffer; } @@ -97,7 +97,7 @@ public: UInt64 startTime; QAudio::Error errorCode; QAudio::State stateCode; - QAudioInputBuffer* audioBuffer; + QtMultimediaInternal::QAudioInputBuffer* audioBuffer; QMutex mutex; QWaitCondition threadFinished; QAtomicInt audioThreadState; diff --git a/src/multimedia/audio/qaudiooutput_alsa_p.cpp b/src/multimedia/audio/qaudiooutput_alsa_p.cpp index b127103..e49c75a 100644 --- a/src/multimedia/audio/qaudiooutput_alsa_p.cpp +++ b/src/multimedia/audio/qaudiooutput_alsa_p.cpp @@ -369,10 +369,52 @@ bool QAudioOutputPrivate::open() } } if ( !fatal ) { + unsigned int maxBufferTime = 0; + unsigned int minBufferTime = 0; + unsigned int maxPeriodTime = 0; + unsigned int minPeriodTime = 0; + + err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &maxBufferTime, &dir); + if ( err >= 0) + err = snd_pcm_hw_params_get_buffer_time_min(hwparams, &minBufferTime, &dir); + if ( err >= 0) + err = snd_pcm_hw_params_get_period_time_max(hwparams, &maxPeriodTime, &dir); + if ( err >= 0) + err = snd_pcm_hw_params_get_period_time_min(hwparams, &minPeriodTime, &dir); + + if ( err < 0 ) { + fatal = true; + errMessage = QString::fromLatin1("QAudioOutput: buffer/period min and max: err = %1").arg(err); + } else { + if (maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time) { +#ifdef DEBUG_AUDIO + qDebug()<<"defaults out of range"; + qDebug()<<"pmin="<<minPeriodTime<<", pmax="<<maxPeriodTime<<", bmin="<<minBufferTime<<", bmax="<<maxBufferTime; +#endif + period_time = minPeriodTime; + if (period_time*4 <= maxBufferTime) { + // Use 4 periods if possible + buffer_time = period_time*4; + chunks = 4; + } else if (period_time*2 <= maxBufferTime) { + // Use 2 periods if possible + buffer_time = period_time*2; + chunks = 2; + } else { + qWarning()<<"QAudioOutput: alsa only supports single period!"; + fatal = true; + } +#ifdef DEBUG_AUDIO + qDebug()<<"used: buffer_time="<<buffer_time<<", period_time="<<period_time; +#endif + } + } + } + if ( !fatal ) { err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); if ( err < 0 ) { fatal = true; - errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); + errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); } } if ( !fatal ) { diff --git a/src/multimedia/audio/qaudiooutput_mac_p.cpp b/src/multimedia/audio/qaudiooutput_mac_p.cpp index 518f78f..6f32257 100644 --- a/src/multimedia/audio/qaudiooutput_mac_p.cpp +++ b/src/multimedia/audio/qaudiooutput_mac_p.cpp @@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE -namespace +namespace QtMultimediaInternal { static const int default_buffer_size = 8 * 1024; @@ -237,7 +237,7 @@ class MacOutputDevice : public QIODevice Q_OBJECT public: - MacOutputDevice(QAudioOutputBuffer* audioBuffer, QObject* parent): + MacOutputDevice(QtMultimediaInternal::QAudioOutputBuffer* audioBuffer, QObject* parent): QIODevice(parent), m_audioBuffer(audioBuffer) { @@ -263,7 +263,7 @@ public: } private: - QAudioOutputBuffer* m_audioBuffer; + QtMultimediaInternal::QAudioOutputBuffer* m_audioBuffer; }; @@ -285,7 +285,7 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray& device, const QAudioF startTime = 0; totalFrames = 0; audioBuffer = 0; - internalBufferSize = default_buffer_size; + internalBufferSize = QtMultimediaInternal::default_buffer_size; clockFrequency = AudioGetHostClockFrequency() / 1000; errorCode = QAudio::NoError; stateCode = QAudio::StoppedState; @@ -399,7 +399,7 @@ bool QAudioOutputPrivate::open() else internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame; - audioBuffer = new QAudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat); + audioBuffer = new QtMultimediaInternal::QAudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat); connect(audioBuffer, SIGNAL(readyRead()), SLOT(inputReady())); // Pull audioIO = new MacOutputDevice(audioBuffer, this); diff --git a/src/multimedia/audio/qaudiooutput_mac_p.h b/src/multimedia/audio/qaudiooutput_mac_p.h index 1aacc67..752905c 100644 --- a/src/multimedia/audio/qaudiooutput_mac_p.h +++ b/src/multimedia/audio/qaudiooutput_mac_p.h @@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE class QIODevice; -namespace +namespace QtMultimediaInternal { class QAudioOutputBuffer; } @@ -96,7 +96,7 @@ public: UInt64 startTime; AudioStreamBasicDescription deviceFormat; AudioStreamBasicDescription streamFormat; - QAudioOutputBuffer* audioBuffer; + QtMultimediaInternal::QAudioOutputBuffer* audioBuffer; QAtomicInt audioThreadState; QWaitCondition threadFinished; QMutex mutex; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index e92b2f3..806452c 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -681,7 +681,11 @@ void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() connection->d_func()->requeueRequest(alreadyPipelinedRequests.at(i)); alreadyPipelinedRequests.clear(); - QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + // only run when the QHttpNetworkConnection is not currently being destructed, e.g. + // this function is called from _q_disconnected which is called because + // of ~QHttpNetworkConnectionPrivate + if (qobject_cast<QHttpNetworkConnection*>(connection)) + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } void QHttpNetworkConnectionChannel::eatWhitespace() diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 93f6d13..4800e9d 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -112,6 +112,13 @@ Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager) To retrieve the name of the local host, use the static QHostInfo::localHostName() function. + \note Since Qt 4.6.1 QHostInfo is using multiple threads for DNS lookup + instead of one dedicated DNS thread. This improves performance, + but also changes the order of signal emissions when using lookupHost() + compared to previous versions of Qt. + \note Since Qt 4.6.3 QHostInfo is using a small internal 60 second DNS cache + for performance improvements. + \sa QAbstractSocket, {http://www.rfc-editor.org/rfc/rfc3492.txt}{RFC 3492} */ @@ -181,9 +188,26 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, receiver, member, Qt::QueuedConnection); result.data()->emitResultsReady(hostInfo); #else - QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id); - QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); - theHostInfoLookupManager()->scheduleLookup(runnable); + QHostInfoLookupManager *manager = theHostInfoLookupManager(); + if (manager) { + // the application is still alive + if (manager->cache.isEnabled()) { + // check cache first + bool valid = false; + QHostInfo info = manager->cache.get(name, &valid); + if (valid) { + info.setLookupId(id); + QHostInfoResult result; + QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + result.emitResultsReady(info); + return id; + } + } + // cache is not enabled or it was not in the cache, do normal lookup + QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id); + QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + manager->scheduleLookup(runnable); + } #endif return id; @@ -418,14 +442,24 @@ void QHostInfoRunnable::run() return; } - // check cache - // FIXME - - // if not in cache: OS lookup - QHostInfo hostInfo = QHostInfoAgent::fromName(toBeLookedUp); - - // save to cache - // FIXME + QHostInfo hostInfo; + + // QHostInfo::lookupHost already checks the cache. However we need to check + // it here too because it might have been cache saved by another QHostInfoRunnable + // in the meanwhile while this QHostInfoRunnable was scheduled but not running + if (manager->cache.isEnabled()) { + // check the cache first + bool valid = false; + hostInfo = manager->cache.get(toBeLookedUp, &valid); + if (!valid) { + // not in cache, we need to do the lookup and store the result in the cache + hostInfo = QHostInfoAgent::fromName(toBeLookedUp); + manager->cache.put(toBeLookedUp, hostInfo); + } + } else { + // cache is not enabled, just do the lookup and continue + hostInfo = QHostInfoAgent::fromName(toBeLookedUp); + } // check aborted again if (manager->wasAborted(id)) { @@ -451,6 +485,11 @@ QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), was QHostInfoLookupManager::~QHostInfoLookupManager() { wasDeleted = true; + + // don't qDeleteAll currentLookups, the QThreadPool has ownership + qDeleteAll(postponedLookups); + qDeleteAll(scheduledLookups); + qDeleteAll(finishedLookups); } void QHostInfoLookupManager::work() @@ -570,6 +609,106 @@ void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r) work(); } +// This function returns immediatly when we had a result in the cache, else it will later emit a signal +QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id) +{ + *valid = false; + *id = -1; + + // check cache + QHostInfoLookupManager* manager = theHostInfoLookupManager(); + if (manager && manager->cache.isEnabled()) { + QHostInfo info = manager->cache.get(name, valid); + if (*valid) { + return info; + } + } + + // was not in cache, trigger lookup + *id = QHostInfo::lookupHost(name, receiver, member); + + // return empty response, valid==false + return QHostInfo(); +} + +void qt_qhostinfo_clear_cache() +{ + QHostInfoLookupManager* manager = theHostInfoLookupManager(); + if (manager) { + manager->cache.clear(); + } +} + +void Q_NETWORK_EXPORT qt_qhostinfo_enable_cache(bool e) +{ + QHostInfoLookupManager* manager = theHostInfoLookupManager(); + if (manager) { + manager->cache.setEnabled(e); + } +} + +// cache for 60 seconds +// cache 64 items +QHostInfoCache::QHostInfoCache() : max_age(60), enabled(true), cache(64) +{ +#ifdef QT_QHOSTINFO_CACHE_DISABLED_BY_DEFAULT + enabled = false; +#endif +} + +bool QHostInfoCache::isEnabled() +{ + return enabled; +} + +// this function is currently only used for the auto tests +// and not usable by public API +void QHostInfoCache::setEnabled(bool e) +{ + enabled = e; +} + + +QHostInfo QHostInfoCache::get(const QString &name, bool *valid) +{ + QMutexLocker locker(&this->mutex); + + *valid = false; + if (cache.contains(name)) { + QHostInfoCacheElement *element = cache.object(name); + if (element->age.elapsed() < max_age*1000) + *valid = true; + return element->info; + + // FIXME idea: + // if too old but not expired, trigger a new lookup + // to freshen our cache + } + + return QHostInfo(); +} + +void QHostInfoCache::put(const QString &name, const QHostInfo &info) +{ + // if the lookup failed, don't cache + if (info.error() != QHostInfo::NoError) + return; + + QHostInfoCacheElement* element = new QHostInfoCacheElement(); + element->info = info; + element->age = QTime(); + element->age.start(); + + QMutexLocker locker(&this->mutex); + cache.insert(name, element); // cache will take ownership +} + +void QHostInfoCache::clear() +{ + QMutexLocker locker(&this->mutex); + cache.clear(); +} + #endif // QT_NO_THREAD QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index d6aa287..2b26b07 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -68,6 +68,8 @@ #include "QtCore/qrunnable.h" #include "QtCore/qlist.h" #include "QtCore/qqueue.h" +#include <QTime> +#include <QCache> #endif QT_BEGIN_NAMESPACE @@ -111,6 +113,34 @@ public: }; #ifndef QT_NO_THREAD +// These functions are outside of the QHostInfo class and strictly internal. +// Do NOT use them outside of QAbstractSocket. +QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id); +void Q_NETWORK_EXPORT qt_qhostinfo_clear_cache(); +void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e); + +class QHostInfoCache +{ +public: + QHostInfoCache(); + const int max_age; // seconds + + QHostInfo get(const QString &name, bool *valid); + void put(const QString &name, const QHostInfo &info); + void clear(); + + bool isEnabled(); + void setEnabled(bool e); +private: + bool enabled; + struct QHostInfoCacheElement { + QHostInfo info; + QTime age; + }; + QCache<QString,QHostInfoCacheElement> cache; + QMutex mutex; +}; + // the following classes are used for the (normal) case: We use multiple threads to lookup DNS class QHostInfoRunnable : public QRunnable @@ -141,6 +171,7 @@ public: void lookupFinished(QHostInfoRunnable *r); bool wasAborted(int id); + QHostInfoCache cache; protected: QList<QHostInfoRunnable*> currentLookups; // in progress QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host @@ -154,6 +185,7 @@ protected: bool wasDeleted; }; + #endif QT_END_NAMESPACE diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 275c436..95721ee 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -172,6 +172,10 @@ This signal is emitted after connectToHost() has been called and the host lookup has succeeded. + \note Since Qt 4.6.3 QAbstractSocket may emit hostFound() + directly from the connectToHost() call since a DNS result could have been + cached. + \sa connected() */ @@ -181,6 +185,10 @@ This signal is emitted after connectToHost() has been called and a connection has been successfully established. + \note On some operating systems the connected() signal may + be directly emitted from the connectToHost() call for connections + to the localhost. + \sa connectToHost(), disconnected() */ @@ -354,6 +362,8 @@ #include "qabstractsocket.h" #include "qabstractsocket_p.h" +#include "private/qhostinfo_p.h" + #include <qabstracteventdispatcher.h> #include <qdatetime.h> #include <qhostaddress.h> @@ -1369,8 +1379,20 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint return; #endif } else { - if (d->threadData->eventDispatcher) - d->hostLookupId = QHostInfo::lookupHost(hostName, this, SLOT(_q_startConnecting(QHostInfo))); + if (d->threadData->eventDispatcher) { + // this internal API for QHostInfo either immediatly gives us the desired + // QHostInfo from cache or later calls the _q_startConnecting slot. + bool immediateResultValid = false; + QHostInfo hostInfo = qt_qhostinfo_lookup(hostName, + this, + SLOT(_q_startConnecting(QHostInfo)), + &immediateResultValid, + &d->hostLookupId); + if (immediateResultValid) { + d->hostLookupId = -1; + d->_q_startConnecting(hostInfo); + } + } } #if defined(QABSTRACTSOCKET_DEBUG) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 25ad5d7..8eb72b0 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1867,6 +1867,7 @@ bool QGL2PaintEngineEx::end() delete d->shaderManager; d->shaderManager = 0; + d->currentBrush = QBrush(); #ifdef QT_OPENGL_CACHE_AS_VBOS if (!d->unusedVBOSToClean.isEmpty()) { diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index c142715..ed34f79 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -64,7 +64,7 @@ #include "qcache.h" #include "qglpaintdevice_p.h" -#ifdef QT_OPENGL_ES +#if defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2) #include <QtGui/private/qegl_p.h> #endif diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 47ce11c..4df894a 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -130,9 +130,8 @@ public: void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD); void stroke(VGPath path, const QPen& pen); void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD); - inline void releasePath(VGPath path); - VGPath vectorPathToVGPath(const QVectorPath& path, bool forceNewPath = false); - VGPath painterPathToVGPath(const QPainterPath& path, bool forceNewPath = false); + VGPath vectorPathToVGPath(const QVectorPath& path); + VGPath painterPathToVGPath(const QPainterPath& path); VGPath roundedRectPath(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode); VGPaintType setBrush (VGPaint paint, const QBrush& brush, VGMatrixMode mode, @@ -178,8 +177,6 @@ public: VGPath roundRectPath; // Cached path for quick drawing of rounded rects. #endif - VGPath reusablePath; // Reusable path for vectorPathToVGPath(), etc. - QTransform transform; // Currently active transform. bool simpleTransform; // True if the transform is simple (non-projective). qreal penScale; // Pen scaling factor from "transform". @@ -352,8 +349,6 @@ void QVGPaintEnginePrivate::init() roundRectPath = 0; #endif - reusablePath = 0; - simpleTransform = true; pathTransformSet = false; penScale = 1.0; @@ -450,15 +445,6 @@ void QVGPaintEnginePrivate::initObjects() VG_PATH_CAPABILITY_ALL); vgAppendPathData(linePath, 2, segments, coords); #endif - - // This path can be reused over and over by calling vgClearPath(). - reusablePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - 32 + 1, // segmentCapacityHint - 32 * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); } void QVGPaintEnginePrivate::destroy() @@ -478,8 +464,6 @@ void QVGPaintEnginePrivate::destroy() if (roundRectPath) vgDestroyPath(roundRectPath); #endif - if (reusablePath) - vgDestroyPath(reusablePath); #if !defined(QVG_NO_DRAW_GLYPHS) QVGFontCache::Iterator it; @@ -531,14 +515,11 @@ void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) 0.0f, -1.0f, 0.0f, 0.5f, devh + 0.5f, 1.0f); - // The image transform is always the full transformation, - // because it can be projective. - imageTransform = transform * viewport; - - // Determine if the transformation is projective. - bool projective = (imageTransform.m13() != 0.0f || - imageTransform.m23() != 0.0f || - imageTransform.m33() != 1.0f); + // Compute the path transform and determine if it is projective. + pathTransform = transform * viewport; + bool projective = (pathTransform.m13() != 0.0f || + pathTransform.m23() != 0.0f || + pathTransform.m33() != 1.0f); if (projective) { // The engine cannot do projective path transforms for us, // so we will have to convert the co-ordinates ourselves. @@ -546,42 +527,37 @@ void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) pathTransform = viewport; simpleTransform = false; } else { - pathTransform = imageTransform; simpleTransform = true; } pathTransformSet = false; + // The image transform is always the full transformation, + // because it can be projective. It also does not need the + // (0.5, -0.5) translation because vgDrawImage() implicitly + // adds 0.5 to each co-ordinate. + QTransform viewport2(1.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, + 0.0f, devh, 1.0f); + imageTransform = transform * viewport2; + // Calculate the scaling factor to use for turning cosmetic pens // into ordinary non-cosmetic pens. qt_scaleForTransform(transform, &penScale); } -inline void QVGPaintEnginePrivate::releasePath(VGPath path) -{ - if (path == reusablePath) - vgClearPath(path, VG_PATH_CAPABILITY_ALL); - else - vgDestroyPath(path); -} - -VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path, bool forceNewPath) +VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path) { int count = path.elementCount(); const qreal *points = path.points(); const QPainterPath::ElementType *elements = path.elements(); - VGPath vgpath; - if (forceNewPath) { - vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - count + 1, // segmentCapacityHint - count * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); - } else { - vgpath = reusablePath; - } + VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); // Size is sufficient segments for drawRoundedRect() paths. QVarLengthArray<VGubyte, 20> segments; @@ -753,22 +729,17 @@ VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path, bool f return vgpath; } -VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path, bool forceNewPath) +VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path) { int count = path.elementCount(); - VGPath vgpath; - if (forceNewPath) { - vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - count + 1, // segmentCapacityHint - count * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); - } else { - vgpath = reusablePath; - } + VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); if (count == 0) return vgpath; @@ -987,7 +958,13 @@ VGPath QVGPaintEnginePrivate::roundedRectPath(const QRectF &rect, qreal xRadius, vgModifyPathCoords(vgpath, 0, 9, pts); } #else - VGPath vgpath = reusablePath; + VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 10, // segmentCapacityHint + 17 * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); vgAppendPathData(vgpath, 10, roundedrect_types, pts); #endif @@ -1540,7 +1517,7 @@ void QVGPaintEngine::draw(const QVectorPath &path) d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); else d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); - d->releasePath(vgpath); + vgDestroyPath(vgpath); } void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush) @@ -1551,7 +1528,7 @@ void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush) d->fill(vgpath, brush, VG_EVEN_ODD); else d->fill(vgpath, brush, VG_NON_ZERO); - d->releasePath(vgpath); + vgDestroyPath(vgpath); } void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen) @@ -1559,7 +1536,7 @@ void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen) Q_D(QVGPaintEngine); VGPath vgpath = d->vectorPathToVGPath(path); d->stroke(vgpath, pen); - d->releasePath(vgpath); + vgDestroyPath(vgpath); } // Determine if a co-ordinate transform is simple enough to allow @@ -1755,7 +1732,7 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) default: break; } - d->releasePath(vgpath); + vgDestroyPath(vgpath); vgSeti(VG_MASKING, VG_TRUE); d->maskValid = true; @@ -2072,7 +2049,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) default: break; } - d->releasePath(vgpath); + vgDestroyPath(vgpath); vgSeti(VG_MASKING, VG_TRUE); d->maskValid = true; @@ -2086,6 +2063,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) void QVGPaintEnginePrivate::ensureMask (QVGPaintEngine *engine, int width, int height) { + scissorMask = false; if (maskIsSet) { vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, width, height); maskRect = QRect(); @@ -2511,7 +2489,7 @@ void QVGPaintEngine::drawRoundedRect(const QRectF &rect, qreal xrad, qreal yrad, VGPath vgpath = d->roundedRectPath(rect, xrad, yrad, mode); d->draw(vgpath, s->pen, s->brush); #if defined(QVG_NO_MODIFY_PATH) - d->releasePath(vgpath); + vgDestroyPath(vgpath); #endif } else { QPaintEngineEx::drawRoundedRect(rect, xrad, yrad, mode); @@ -2660,7 +2638,13 @@ void QVGPaintEngine::drawEllipse(const QRectF &r) Q_D(QVGPaintEngine); if (d->simpleTransform) { QVGPainterState *s = state(); - VGPath path = d->reusablePath; + VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 4, // segmentCapacityHint + 12, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); static VGubyte segments[4] = { VG_MOVE_TO_ABS, VG_SCCWARC_TO_REL, @@ -2684,7 +2668,7 @@ void QVGPaintEngine::drawEllipse(const QRectF &r) coords[11] = 0.0f; vgAppendPathData(path, 4, segments, coords); d->draw(path, s->pen, s->brush); - d->releasePath(path); + vgDestroyPath(path); } else { // The projective transform version of an ellipse is difficult. // Generate a QVectorPath containing cubic curves and transform that. @@ -2708,7 +2692,7 @@ void QVGPaintEngine::drawPath(const QPainterPath &path) d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); else d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); - d->releasePath(vgpath); + vgDestroyPath(vgpath); } void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount) @@ -2783,7 +2767,13 @@ void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonD { Q_D(QVGPaintEngine); QVGPainterState *s = state(); - VGPath path = d->reusablePath; + VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + pointCount + 1, // segmentCapacityHint + pointCount * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); QVarLengthArray<VGfloat, 16> coords; QVarLengthArray<VGubyte, 10> segments; for (int i = 0; i < pointCount; ++i, ++points) { @@ -2817,14 +2807,20 @@ void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonD d->draw(path, s->pen, s->brush, VG_EVEN_ODD); break; } - d->releasePath(path); + vgDestroyPath(path); } void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) { Q_D(QVGPaintEngine); QVGPainterState *s = state(); - VGPath path = d->reusablePath; + VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + pointCount + 1, // segmentCapacityHint + pointCount * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); QVarLengthArray<VGfloat, 16> coords; QVarLengthArray<VGubyte, 10> segments; for (int i = 0; i < pointCount; ++i, ++points) { @@ -2858,7 +2854,7 @@ void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDr d->draw(path, s->pen, s->brush, VG_EVEN_ODD); break; } - d->releasePath(path); + vgDestroyPath(path); } void QVGPaintEnginePrivate::setImageOptions() @@ -3255,7 +3251,7 @@ void QVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, fontEngine->getUnscaledGlyph(glyph, &path, &metrics); VGPath vgPath; if (!path.isEmpty()) { - vgPath = d->painterPathToVGPath(path, true); + vgPath = d->painterPathToVGPath(path); } else { // Probably a "space" character with no visible outline. vgPath = VG_INVALID_HANDLE; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 12f4c6b..54f4a8a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -68,11 +68,10 @@ public: }; enum CompositionModeStatus { - PorterDuff_None = 0x00, - PorterDuff_SupportedBlits = 0x01, - PorterDuff_SupportedPrimitives = 0x02, - PorterDuff_SupportedOpaquePrimitives = 0x04, - PorterDuff_Dirty = 0x10 + PorterDuff_None = 0x0, + PorterDuff_Supported = 0x1, + PorterDuff_PremultiplyColors = 0x2, + PorterDuff_AlwaysBlend = 0x4 }; enum ClipType { @@ -97,7 +96,6 @@ public: inline void unlock(); static inline void unlock(QDirectFBPaintDevice *device); - inline bool testCompositionMode(const QPen *pen, const QBrush *brush, const QColor *color = 0) const; inline bool isSimpleBrush(const QBrush &brush) const; void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos); @@ -130,6 +128,7 @@ public: ClipType clipType; QDirectFBPaintDevice *dfbDevice; uint compositionModeStatus; + bool isPremultiplied; bool inClip; QRect currentClip; @@ -168,7 +167,7 @@ struct CachedImage static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB #endif -#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS +#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS || defined QT_DEBUG #define VOID_ARG() static_cast<bool>(false) enum PaintOperation { DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004, @@ -178,9 +177,89 @@ enum PaintOperation { FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000, DRAW_STATICTEXT = 0x8000, ALL = 0xffff }; + +#ifdef QT_DEBUG +static void initRasterFallbacksMasks(int *warningMask, int *disableMask) +{ + struct { + const char *name; + PaintOperation operation; + } const operations[] = { + { "DRAW_RECTS", DRAW_RECTS }, + { "DRAW_LINES", DRAW_LINES }, + { "DRAW_IMAGE", DRAW_IMAGE }, + { "DRAW_PIXMAP", DRAW_PIXMAP }, + { "DRAW_TILED_PIXMAP", DRAW_TILED_PIXMAP }, + { "STROKE_PATH", STROKE_PATH }, + { "DRAW_PATH", DRAW_PATH }, + { "DRAW_POINTS", DRAW_POINTS }, + { "DRAW_ELLIPSE", DRAW_ELLIPSE }, + { "DRAW_POLYGON", DRAW_POLYGON }, + { "DRAW_TEXT", DRAW_TEXT }, + { "FILL_PATH", FILL_PATH }, + { "FILL_RECT", FILL_RECT }, + { "DRAW_COLORSPANS", DRAW_COLORSPANS }, + { "DRAW_ROUNDED_RECT", DRAW_ROUNDED_RECT }, + { "ALL", ALL }, + { 0, ALL } + }; + + QStringList warning = QString::fromLatin1(qgetenv("QT_DIRECTFB_WARN_ON_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'), + QString::SkipEmptyParts); + QStringList disable = QString::fromLatin1(qgetenv("QT_DIRECTFB_DISABLE_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'), + QString::SkipEmptyParts); + *warningMask = 0; + *disableMask = 0; + if (!warning.isEmpty() || !disable.isEmpty()) { + for (int i=0; operations[i].name; ++i) { + const QString name = QString::fromLatin1(operations[i].name); + int idx = warning.indexOf(name); + if (idx != -1) { + *warningMask |= operations[i].operation; + warning.remove(warning.begin() + idx); + } + idx = disable.indexOf(name); + if (idx != -1) { + *disableMask |= operations[i].operation; + disable.remove(disable.begin() + idx); + } + } + } + if (!warning.isEmpty()) { + qWarning("QDirectFBPaintEngine QT_DIRECTFB_WARN_ON_RASTERFALLBACKS Unknown operation(s): %s", + qPrintable(warning.join(QLatin1String("|")))); + } + if (!disable.isEmpty()) { + qWarning("QDirectFBPaintEngine QT_DIRECTFB_DISABLE_RASTERFALLBACKS Unknown operation(s): %s", + qPrintable(disable.join(QLatin1String("|")))); + } + +} #endif +static inline int rasterFallbacksMask(bool warn) +{ #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS + if (warn) + return QT_DIRECTFB_WARN_ON_RASTERFALLBACKS; +#endif +#ifdef QT_DIRECTFB_DISABLE_RASTERFALLBACKS + if (!warn) + return QT_DIRECTFB_DISABLE_RASTERFALLBACKS; +#endif +#ifndef QT_DEBUG + return 0; +#else + static int warnMask = -1; + static int disableMask = -1; + if (warnMask == -1) + initRasterFallbacksMasks(&warnMask, &disableMask); + return warn ? warnMask : disableMask; +#endif +} +#endif + +#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DEBUG template <typename device, typename T1, typename T2, typename T3> static void rasterFallbackWarn(const char *msg, const char *func, const device *dev, uint transformationType, bool simplePen, @@ -190,25 +269,31 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * const char *nameThree, const T3 &three); #endif -#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS +#if defined QT_DEBUG || (defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS) #define RASTERFALLBACK(op, one, two, three) \ - if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ - rasterFallbackWarn("Disabled raster engine operation", \ - __FUNCTION__, state()->painter->device(), \ - d_func()->transformationType, \ - d_func()->simplePen, \ - d_func()->clipType, \ - d_func()->compositionModeStatus, \ - #one, one, #two, two, #three, three); \ - if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \ - return; + { \ + const bool disable = op & rasterFallbacksMask(false); \ + if (op & rasterFallbacksMask(true)) \ + rasterFallbackWarn(disable \ + ? "Disabled raster engine operation" \ + : "Falling back to raster engine for", \ + __FUNCTION__, \ + state()->painter->device(), \ + d_func()->transformationType, \ + d_func()->simplePen, \ + d_func()->clipType, \ + d_func()->compositionModeStatus, \ + #one, one, #two, two, #three, three); \ + if (disable) \ + return; \ + } #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS -#define RASTERFALLBACK(op, one, two, three) \ - if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \ +#define RASTERFALLBACK(op, one, two, three) \ + if (op & rasterFallbacksMask(false)) \ return; #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS #define RASTERFALLBACK(op, one, two, three) \ - if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ + if (op & rasterFallbacksMask(true)) \ rasterFallbackWarn("Falling back to raster engine for", \ __FUNCTION__, state()->painter->device(), \ d_func()->transformationType, \ @@ -287,6 +372,7 @@ bool QDirectFBPaintEngine::begin(QPaintDevice *device) qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", device->devType()); } + d->isPremultiplied = QDirectFBScreen::isPremultiplied(d->dfbDevice->format()); d->prepare(d->dfbDevice); gccaps = AllFeatures; @@ -413,7 +499,7 @@ void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount) || !d->simplePen || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip || !d->isSimpleBrush(brush) - || !d->testCompositionMode(&pen, &brush)) { + || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawRects(rects, rectCount); @@ -443,7 +529,7 @@ void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount) || !d->simplePen || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip || !d->isSimpleBrush(brush) - || !d->testCompositionMode(&pen, &brush)) { + || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawRects(rects, rectCount); @@ -468,7 +554,7 @@ void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount) const QPen &pen = state()->pen; if (!d->simplePen || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip - || !d->testCompositionMode(&pen, 0)) { + || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawLines(lines, lineCount); @@ -488,7 +574,7 @@ void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount) const QPen &pen = state()->pen; if (!d->simplePen || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip - || !d->testCompositionMode(&pen, 0)) { + || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); d->lock(); QRasterPaintEngine::drawLines(lines, lineCount); @@ -526,7 +612,7 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, */ #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE - if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) + if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size()) @@ -575,7 +661,7 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, QPixmapData *data = pixmap.pixmapData(); Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); - if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) + if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())) { @@ -606,7 +692,7 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); d->lock(); QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset); - } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) + } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) || (!d->supportsStretchBlit() && state()->matrix.isScaling())) { @@ -727,20 +813,21 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) { switch (brush.style()) { case Qt::SolidPattern: { - if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported - || !d->testCompositionMode(0, &brush)) { - break; - } const QColor color = brush.color(); if (!color.isValid()) return; + + if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported + || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { + break; + } d->setDFBColor(color); const QRect r = state()->matrix.mapRect(rect).toRect(); CLIPPED_PAINT(d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height())); return; } case Qt::TexturePattern: { - if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) + if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) || (!d->supportsStretchBlit() && state()->matrix.isScaling())) { break; @@ -768,7 +855,7 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color) Q_D(QDirectFBPaintEngine); if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported) || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) - || !d->testCompositionMode(0, 0, &color)) { + || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG()); d->lock(); QRasterPaintEngine::fillRect(rect, color); @@ -812,7 +899,7 @@ QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p : surface(0), antialiased(false), simplePen(false), transformationType(0), opacity(255), clipType(ClipUnset), dfbDevice(0), - compositionModeStatus(0), inClip(false), q(p) + compositionModeStatus(0), isPremultiplied(false), inClip(false), q(p) { fb = QDirectFBScreen::instance()->dfb(); surfaceCache = new SurfaceCache; @@ -828,36 +915,6 @@ bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); } -bool QDirectFBPaintEnginePrivate::testCompositionMode(const QPen *pen, const QBrush *brush, const QColor *color) const -{ - Q_ASSERT(!pen || pen->style() == Qt::NoPen || pen->style() == Qt::SolidLine); - Q_ASSERT(!brush || brush->style() == Qt::NoBrush || brush->style() == Qt::SolidPattern); - switch (compositionModeStatus & (QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives - |QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives)) { - case QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives: - return true; - case QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives: - if (pen && pen->style() == Qt::SolidLine && pen->color().alpha() != 255) - return false; - if (brush) { - if (brush->style() == Qt::SolidPattern && brush->color().alpha() != 255) { - return false; - } - } else if (color && color->alpha() != 255) { - return false; - } - return true; - case QDirectFBPaintEnginePrivate::PorterDuff_None: - return false; - default: - // ### PorterDuff_SupportedOpaquePrimitives|PorterDuff_SupportedPrimitives can't be combined - break; - } - Q_ASSERT(0); - return false; -} - - void QDirectFBPaintEnginePrivate::lock() { // We will potentially get a new pointer to the buffer after a @@ -920,21 +977,23 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0; if (forceRasterFallBack) { - compositionModeStatus = 0; + compositionModeStatus = PorterDuff_None; return; } - compositionModeStatus = PorterDuff_SupportedBlits; + compositionModeStatus = PorterDuff_Supported|PorterDuff_PremultiplyColors|PorterDuff_AlwaysBlend; switch (mode) { case QPainter::CompositionMode_Clear: surface->SetPorterDuff(surface, DSPD_CLEAR); break; case QPainter::CompositionMode_Source: surface->SetPorterDuff(surface, DSPD_SRC); - compositionModeStatus |= PorterDuff_SupportedOpaquePrimitives; + compositionModeStatus &= ~PorterDuff_AlwaysBlend; + if (!isPremultiplied) + compositionModeStatus &= ~PorterDuff_PremultiplyColors; break; case QPainter::CompositionMode_SourceOver: - compositionModeStatus |= PorterDuff_SupportedPrimitives; + compositionModeStatus &= ~PorterDuff_AlwaysBlend; surface->SetPorterDuff(surface, DSPD_SRC_OVER); break; case QPainter::CompositionMode_DestinationOver: @@ -942,6 +1001,8 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m break; case QPainter::CompositionMode_SourceIn: surface->SetPorterDuff(surface, DSPD_SRC_IN); + if (!isPremultiplied) + compositionModeStatus &= ~PorterDuff_PremultiplyColors; break; case QPainter::CompositionMode_DestinationIn: surface->SetPorterDuff(surface, DSPD_DST_IN); @@ -952,6 +1013,11 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m case QPainter::CompositionMode_DestinationOut: surface->SetPorterDuff(surface, DSPD_DST_OUT); break; +#if (Q_DIRECTFB_VERSION >= 0x010209) + case QPainter::CompositionMode_Destination: + surface->SetPorterDuff(surface, DSPD_DST); + break; +#endif #if (Q_DIRECTFB_VERSION >= 0x010000) case QPainter::CompositionMode_SourceAtop: surface->SetPorterDuff(surface, DSPD_SRC_ATOP); @@ -967,7 +1033,7 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m break; #endif default: - compositionModeStatus = 0; + compositionModeStatus = PorterDuff_None; break; } } @@ -989,9 +1055,6 @@ void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) } surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); surface->SetBlittingFlags(surface, blittingFlags); - if (compositionModeStatus & PorterDuff_Dirty) { - setCompositionMode(q->state()->composition_mode); - } } static inline uint ALPHA_MUL(uint x, uint a) @@ -1004,12 +1067,20 @@ static inline uint ALPHA_MUL(uint x, uint a) void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) { Q_ASSERT(surface); + Q_ASSERT(compositionModeStatus & PorterDuff_Supported); const quint8 alpha = (opacity == 255 ? color.alpha() : ALPHA_MUL(color.alpha(), opacity)); - surface->SetColor(surface, color.red(), color.green(), color.blue(), alpha); - surface->SetPorterDuff(surface, DSPD_NONE); - surface->SetDrawingFlags(surface, alpha == 255 ? DSDRAW_NOFX : DSDRAW_BLEND); - compositionModeStatus |= PorterDuff_Dirty; + QColor col; + if (compositionModeStatus & PorterDuff_PremultiplyColors) { + col = QColor(ALPHA_MUL(color.red(), alpha), + ALPHA_MUL(color.green(), alpha), + ALPHA_MUL(color.blue(), alpha), + alpha); + } else { + col = QColor(color.red(), color.green(), color.blue(), alpha); + } + surface->SetColor(surface, col.red(), col.green(), col.blue(), col.alpha()); + surface->SetDrawingFlags(surface, alpha == 255 && !(compositionModeStatus & PorterDuff_AlwaysBlend) ? DSDRAW_NOFX : DSDRAW_BLEND); } IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release) @@ -1291,7 +1362,7 @@ static inline void drawRects(const T *rects, int n, const QTransform &transform, } } -#ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS +#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DEBUG template <typename T> inline const T *ptr(const T &t) { return &t; } template <> inline const bool* ptr<bool>(const bool &) { return 0; } template <typename device, typename T1, typename T2, typename T3> diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index ba50329..b5ac67d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -425,7 +425,7 @@ void QDirectFBPixmapData::fill(const QColor &color) Q_ASSERT(dfbSurface); - alpha = (color.alpha() < 255); + alpha |= (color.alpha() < 255); if (alpha && isOpaqueFormat(imageFormat)) { QSize size; diff --git a/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp b/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp index 7bcb74d..e78fec1 100644 --- a/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp +++ b/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp @@ -325,6 +325,36 @@ static const struct { { 0xffe8, Qt::Key_Meta }, { 0xffe9, Qt::Key_Alt }, { 0xffea, Qt::Key_Alt }, + + { 0xffb0, Qt::Key_0 }, + { 0xffb1, Qt::Key_1 }, + { 0xffb2, Qt::Key_2 }, + { 0xffb3, Qt::Key_3 }, + { 0xffb4, Qt::Key_4 }, + { 0xffb5, Qt::Key_5 }, + { 0xffb6, Qt::Key_6 }, + { 0xffb7, Qt::Key_7 }, + { 0xffb8, Qt::Key_8 }, + { 0xffb9, Qt::Key_9 }, + + { 0xff8d, Qt::Key_Return }, + { 0xffaa, Qt::Key_Asterisk }, + { 0xffab, Qt::Key_Plus }, + { 0xffad, Qt::Key_Minus }, + { 0xffae, Qt::Key_Period }, + { 0xffaf, Qt::Key_Slash }, + + { 0xff95, Qt::Key_Home }, + { 0xff96, Qt::Key_Left }, + { 0xff97, Qt::Key_Up }, + { 0xff98, Qt::Key_Right }, + { 0xff99, Qt::Key_Down }, + { 0xff9a, Qt::Key_PageUp }, + { 0xff9b, Qt::Key_PageDown }, + { 0xff9c, Qt::Key_End }, + { 0xff9e, Qt::Key_Insert }, + { 0xff9f, Qt::Key_Delete }, + { 0, 0 } }; @@ -483,6 +513,10 @@ bool QRfbKeyEvent::read(QTcpSocket *s) keycode = keyMap[i].keycode; i++; } + + if (keycode >= ' ' && keycode <= '~') + unicode = keycode; + if (!keycode) { if (key <= 0xff) { unicode = key; diff --git a/src/plugins/sqldrivers/odbc/odbc.pro b/src/plugins/sqldrivers/odbc/odbc.pro index 3de8ab2..2bf85f1 100644 --- a/src/plugins/sqldrivers/odbc/odbc.pro +++ b/src/plugins/sqldrivers/odbc/odbc.pro @@ -8,6 +8,7 @@ unix { !contains( LIBS, .*odbc.* ) { LIBS *= $$QT_LFLAGS_ODBC } + DEFINES += UNICODE } win32 { diff --git a/src/sql/drivers/drivers.pri b/src/sql/drivers/drivers.pri index aac0267..8dfc50f 100644 --- a/src/sql/drivers/drivers.pri +++ b/src/sql/drivers/drivers.pri @@ -46,6 +46,7 @@ contains(sql-drivers, odbc) { mac:!contains( LIBS, .*odbc.* ):LIBS *= -liodbc unix:!contains( LIBS, .*odbc.* ):LIBS *= -lodbc + unix:DEFINES += UNICODE win32 { !win32-borland:LIBS *= -lodbc32 diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index c0f866e..2261887 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -320,6 +320,16 @@ static bool qIsBlob(int t) || t == MYSQL_TYPE_LONG_BLOB; } +static bool qIsInteger(int t) +{ + return t == MYSQL_TYPE_TINY + || t == MYSQL_TYPE_SHORT + || t == MYSQL_TYPE_LONG + || t == MYSQL_TYPE_LONGLONG + || t == MYSQL_TYPE_INT24; +} + + void QMYSQLResultPrivate::bindBlobs() { int i; @@ -368,6 +378,13 @@ bool QMYSQLResultPrivate::bindInValues() fieldInfo->length = 0; hasBlobs = true; } else { + // fieldInfo->length specifies the display width, which may be too + // small to hold valid integer values (see + // http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html ), so + // always use the MAX_BIGINT_WIDTH for integer types + if (qIsInteger(fieldInfo->type)) { + fieldInfo->length = MAX_BIGINT_WIDTH; + } fieldInfo->type = MYSQL_TYPE_STRING; } bind = &inBinds[i]; diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 9f7d267..ee22bc3 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -71,11 +71,54 @@ QT_BEGIN_NAMESPACE # define QSQLULEN SQLULEN #endif - static const int COLNAMESIZE = 256; //Map Qt parameter types to ODBC types static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT }; +inline static QString fromSQLTCHAR(const QVarLengthArray<SQLTCHAR>& input, int size=-1) +{ + QString result; + + int realsize = qMin(size, input.size()); + if(realsize > 0 && input[realsize-1] == 0) + realsize--; + switch(sizeof(SQLTCHAR)) { + case 1: + result=QString::fromUtf8((const char *)input.constData(), realsize); + break; + case 2: + result=QString::fromUtf16((const ushort *)input.constData(), realsize); + break; + case 4: + result=QString::fromUcs4((const uint *)input.constData(), realsize); + break; + default: + qCritical() << "sizeof(SQLTCHAR) is " << sizeof(SQLTCHAR) << "Don't know how to handle this"; + } + return result; +} + +inline static QVarLengthArray<SQLTCHAR> toSQLTCHAR(const QString &input) +{ + QVarLengthArray<SQLTCHAR> result; + result.resize(input.size()); + switch(sizeof(SQLTCHAR)) { + case 1: + memcpy(result.data(), input.toUtf8().data(), input.size()); + break; + case 2: + memcpy(result.data(), input.unicode(), input.size() * 2); + break; + case 4: + memcpy(result.data(), input.toUcs4().data(), input.size() * 4); + break; + default: + qCritical() << "sizeof(SQLTCHAR) is " << sizeof(SQLTCHAR) << "Don't know how to handle this"; + } + result.append(0); // make sure it's null terminated, doesn't matter if it already is, it does if it isn't. + return result; +} + class QODBCDriverPrivate { public: @@ -91,8 +134,8 @@ public: SQLHANDLE hEnv; SQLHANDLE hDbc; - uint unicode :1; - uint useSchema :1; + bool unicode; + bool useSchema; int disconnectCount; bool isMySqlServer; bool isMSSqlServer; @@ -132,8 +175,8 @@ public: SQLHANDLE dpDbc() const { return driverPrivate ? driverPrivate->hDbc : 0;} SQLHANDLE hStmt; - uint unicode :1; - uint useSchema :1; + bool unicode; + bool useSchema; QSqlRecord rInf; QVector<QVariant> fieldCache; @@ -170,19 +213,18 @@ static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode int i = 1; description_[0] = 0; - r = SQLGetDiagRec(handleType, - handle, - i, - state_, - &nativeCode_, - 0, - NULL, - &msgLen); - if(r == SQL_NO_DATA) - return QString(); - description_.resize(msgLen+1); do { r = SQLGetDiagRec(handleType, + handle, + i, + state_, + &nativeCode_, + 0, + NULL, + &msgLen); + if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && msgLen > 0) + description_.resize(msgLen+1); + r = SQLGetDiagRec(handleType, handle, i, state_, @@ -195,9 +237,9 @@ static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode *nativeCode = nativeCode_; QString tmpstore; #ifdef UNICODE - tmpstore = QString((const QChar*)description_.data(), msgLen); + tmpstore = fromSQLTCHAR(description_, msgLen); #else - tmpstore = QString::fromLocal8Bit((const char*)description_.data(), msgLen); + tmpstore = QString::fromUtf8((const char*)description_.constData(), msgLen); #endif if(result != tmpstore) { if(!result.isEmpty()) @@ -216,13 +258,13 @@ static QString qODBCWarn(const QODBCPrivate* odbc, int *nativeCode = 0) { return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->dpEnv()) + QLatin1Char(' ') + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->dpDbc()) + QLatin1Char(' ') - + qWarnODBCHandle(SQL_HANDLE_STMT, odbc->hStmt, nativeCode)); + + qWarnODBCHandle(SQL_HANDLE_STMT, odbc->hStmt, nativeCode)).simplified(); } static QString qODBCWarn(const QODBCDriverPrivate* odbc, int *nativeCode = 0) { return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1Char(' ') - + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode)); + + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode)).simplified(); } static void qSqlWarning(const QString& message, const QODBCPrivate* odbc) @@ -322,17 +364,22 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni colSize = 65536; } else { colSize++; // make sure there is room for more than the 0 termination - if (unicode) { - colSize *= 2; // a tiny bit faster, since it saves a SQLGetData() call - } } - QVarLengthArray<char> buf(colSize); + r = SQLGetData(hStmt, + column+1, + SQL_C_TCHAR, + NULL, + 0, + &lengthIndicator); + if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0) + colSize = lengthIndicator/sizeof(SQLTCHAR) + 1; + QVarLengthArray<SQLTCHAR> buf(colSize); while (true) { r = SQLGetData(hStmt, column+1, - unicode ? SQL_C_WCHAR : SQL_C_CHAR, + SQL_C_TCHAR, (SQLPOINTER)buf.data(), - colSize, + colSize*sizeof(SQLTCHAR), &lengthIndicator); if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) { @@ -344,14 +391,9 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni // contain the number of bytes returned - it contains the // total number of bytes that CAN be fetched // colSize-1: remove 0 termination when there is more data to fetch - int rSize = (r == SQL_SUCCESS_WITH_INFO) ? (unicode ? colSize-2 : colSize-1) : lengthIndicator; - if (unicode) { - fieldVal += QString((const QChar*) buf.constData(), rSize / 2); - } else { - fieldVal += QString::fromAscii(buf.constData(), rSize); - } - memset(buf.data(), 0, colSize); - if (lengthIndicator < colSize) { + int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator/sizeof(SQLTCHAR); + fieldVal += fromSQLTCHAR(buf, rSize); + if (lengthIndicator < (unsigned int)colSize*sizeof(SQLTCHAR)) { // workaround for Drivermanagers that don't return SQL_NO_DATA break; } @@ -377,10 +419,11 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) QSQLLEN lengthIndicator = 0; SQLRETURN r = SQL_ERROR; - SQLTCHAR colName[COLNAMESIZE]; + QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE); + r = SQLDescribeCol(hStmt, column + 1, - colName, + colName.data(), COLNAMESIZE, &colNameLen, &colType, @@ -513,10 +556,10 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) SQLSMALLINT colScale; SQLSMALLINT nullable; SQLRETURN r = SQL_ERROR; - SQLTCHAR colName[COLNAMESIZE]; + QVarLengthArray<SQLTCHAR> colName(COLNAMESIZE); r = SQLDescribeCol(p->hStmt, i+1, - colName, + colName.data(), (SQLSMALLINT)COLNAMESIZE, &colNameLen, &colType, @@ -542,9 +585,9 @@ static QSqlField qMakeFieldInfo(const QODBCPrivate* p, int i ) } #ifdef UNICODE - QString qColName((const QChar*)colName, colNameLen); + QString qColName(fromSQLTCHAR(colName, colNameLen)); #else - QString qColName = QString::fromLocal8Bit((const char*)colName); + QString qColName = QString::fromUtf8((const char *)colName.constData()); #endif // nullable can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN int required = -1; @@ -576,18 +619,21 @@ static int qGetODBCVersion(const QString &connOpts) QChar QODBCDriverPrivate::quoteChar() { if (!isQuoteInitialized) { - char driverResponse[4]; + SQLTCHAR driverResponse[4]; SQLSMALLINT length; int r = SQLGetInfo(hDbc, SQL_IDENTIFIER_QUOTE_CHAR, &driverResponse, sizeof(driverResponse), &length); - if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { + if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) +#ifdef UNICODE + quote = QChar(driverResponse[0]); +#else quote = QLatin1Char(driverResponse[0]); - } else { +#endif + else quote = QLatin1Char('"'); - } isQuoteInitialized = true; } return quote; @@ -631,11 +677,11 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts) val.utf16(); // 0 terminate r = SQLSetConnectAttr(hDbc, SQL_ATTR_CURRENT_CATALOG, #ifdef UNICODE - (SQLWCHAR*) val.unicode(), + toSQLTCHAR(val).data(), #else - (SQLCHAR*) val.toLatin1().constData(), + (SQLCHAR*) val.toUtf8().data(), #endif - SQL_NTS); + val.length()*sizeof(SQLTCHAR)); } else if (opt.toUpper() == QLatin1String("SQL_ATTR_METADATA_ID")) { if (val.toUpper() == QLatin1String("SQL_TRUE")) { v = SQL_TRUE; @@ -653,11 +699,11 @@ bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts) val.utf16(); // 0 terminate r = SQLSetConnectAttr(hDbc, SQL_ATTR_TRACEFILE, #ifdef UNICODE - (SQLWCHAR*) val.unicode(), + toSQLTCHAR(val).data(), #else - (SQLCHAR*) val.toLatin1().constData(), + (SQLCHAR*) val.toUtf8().data(), #endif - SQL_NTS); + val.length()*sizeof(SQLTCHAR)); } else if (opt.toUpper() == QLatin1String("SQL_ATTR_TRACE")) { if (val.toUpper() == QLatin1String("SQL_OPT_TRACE_OFF")) { v = SQL_OPT_TRACE_OFF; @@ -867,12 +913,12 @@ bool QODBCResult::reset (const QString& query) #ifdef UNICODE r = SQLExecDirect(d->hStmt, - (SQLWCHAR*) query.unicode(), + toSQLTCHAR(query).data(), (SQLINTEGER) query.length()); #else - QByteArray query8 = query.toLocal8Bit(); + QByteArray query8 = query.toUtf8(); r = SQLExecDirect(d->hStmt, - (SQLCHAR*) query8.constData(), + (SQLCHAR*) query8.data(), (SQLINTEGER) query8.length()); #endif if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r!= SQL_NO_DATA) { @@ -1218,12 +1264,12 @@ bool QODBCResult::prepare(const QString& query) #ifdef UNICODE r = SQLPrepare(d->hStmt, - (SQLWCHAR*) query.unicode(), + toSQLTCHAR(query).data(), (SQLINTEGER) query.length()); #else - QByteArray query8 = query.toLocal8Bit(); + QByteArray query8 = query.toUtf8(); r = SQLPrepare(d->hStmt, - (SQLCHAR*) query8.constData(), + (SQLCHAR*) query8.data(), (SQLINTEGER) query8.length()); #endif @@ -1421,42 +1467,43 @@ bool QODBCResult::exec() case QVariant::String: if (d->unicode) { QString str = val.toString(); - str.utf16(); if (*ind != SQL_NULL_DATA) - *ind = str.length() * sizeof(QChar); - int strSize = str.length() * sizeof(QChar); + *ind = str.length() * sizeof(SQLTCHAR); + int strSize = str.length() * sizeof(SQLTCHAR); if (bindValueType(i) & QSql::Out) { - QByteArray ba((char*)str.constData(), str.capacity() * sizeof(QChar)); + QVarLengthArray<SQLTCHAR> ba(toSQLTCHAR(str)); + ba.reserve(str.capacity()); r = SQLBindParameter(d->hStmt, i + 1, qParamType[(QFlag)(bindValueType(i)) & QSql::InOut], - SQL_C_WCHAR, + SQL_C_TCHAR, strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, 0, // god knows... don't change this! 0, (void *)ba.constData(), ba.size(), ind); - tmpStorage.append(ba); + tmpStorage.append(QByteArray((const char *)ba.constData(), ba.size()*sizeof(SQLTCHAR))); break; } - + QByteArray strba((const char *)toSQLTCHAR(str).constData(), str.size()*sizeof(SQLTCHAR)); r = SQLBindParameter(d->hStmt, i + 1, qParamType[(QFlag)(bindValueType(i)) & QSql::InOut], - SQL_C_WCHAR, + SQL_C_TCHAR, strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, strSize, 0, - (void *)str.constData(), - strSize, + (SQLPOINTER)strba.constData(), + strba.size(), ind); + tmpStorage.append(strba); break; } else { - QByteArray str = val.toString().toAscii(); + QByteArray str = val.toString().toUtf8(); if (*ind != SQL_NULL_DATA) *ind = str.length(); int strSize = str.length(); @@ -1557,15 +1604,18 @@ bool QODBCResult::exec() break; case QVariant::String: if (d->unicode) { - if (bindValueType(i) & QSql::Out) - values[i] = QString((QChar *)tmpStorage.takeFirst().constData()); + if (bindValueType(i) & QSql::Out) { + QByteArray first = tmpStorage.takeFirst(); + QVarLengthArray<SQLTCHAR> array; + array.append((SQLTCHAR *)first.constData(), first.size()); + values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR*)); + } break; } // fall through default: { - QByteArray ba = tmpStorage.takeFirst(); if (bindValueType(i) & QSql::Out) - values[i] = QString::fromAscii(ba.constData()); + values[i] = tmpStorage.takeFirst(); break; } } if (indicators[i] == SQL_NULL_DATA) @@ -1774,19 +1824,20 @@ bool QODBCDriver::open(const QString & db, connQStr += QLatin1String(";PWD=") + password; SQLSMALLINT cb; - SQLTCHAR connOut[1024]; + QVarLengthArray<SQLTCHAR> connOut(1024); r = SQLDriverConnect(d->hDbc, NULL, #ifdef UNICODE - (SQLWCHAR*)connQStr.unicode(), + toSQLTCHAR(connQStr).data(), #else - (SQLCHAR*)connQStr.toLatin1().constData(), + (SQLCHAR*)connQStr.toUtf8().data(), #endif (SQLSMALLINT)connQStr.length(), - connOut, + connOut.data(), 1024, &cb, - SQL_DRIVER_NOPROMPT); + /*SQL_DRIVER_NOPROMPT*/0); + if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) { setLastError(qMakeError(tr("Unable to connect"), QSqlError::ConnectionError, d)); setOpenError(true); @@ -1957,20 +2008,21 @@ void QODBCDriverPrivate::checkSchemaUsage() void QODBCDriverPrivate::checkSqlServer() { SQLRETURN r; - char serverString[200]; + QVarLengthArray<SQLTCHAR> serverString(200); SQLSMALLINT t; + memset(serverString.data(), 0, serverString.size() * sizeof(SQLTCHAR)); r = SQLGetInfo(hDbc, SQL_DBMS_NAME, - serverString, - sizeof(serverString), + serverString.data(), + serverString.size() * sizeof(SQLTCHAR), &t); if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { QString serverType; #ifdef UNICODE - serverType = QString(reinterpret_cast<const QChar*>(serverString), t/sizeof(QChar)); + serverType = fromSQLTCHAR(serverString, t/sizeof(SQLTCHAR)); #else - serverType = QString::fromLocal8Bit(serverString, t); + serverType = QString::fromUtf8((const char *)serverString.constData(), t); #endif isMySqlServer = serverType.contains(QLatin1String("mysql"), Qt::CaseInsensitive); isMSSqlServer = serverType.contains(QLatin1String("Microsoft SQL Server"), Qt::CaseInsensitive); @@ -1989,18 +2041,18 @@ void QODBCDriverPrivate::checkHasSQLFetchScroll() void QODBCDriverPrivate::checkHasMultiResults() { - char driverResponse[4]; + QVarLengthArray<SQLTCHAR> driverResponse(2); SQLSMALLINT length; SQLRETURN r = SQLGetInfo(hDbc, SQL_MULT_RESULT_SETS, - driverResponse, - sizeof(driverResponse), + driverResponse.data(), + driverResponse.size() * sizeof(SQLTCHAR), &length); if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) #ifdef UNICODE - hasMultiResultSets = QString(reinterpret_cast<const QChar*>(driverResponse), length/sizeof(QChar)).startsWith(QLatin1Char('Y')); + hasMultiResultSets = fromSQLTCHAR(driverResponse, length/sizeof(SQLTCHAR)).startsWith(QLatin1Char('Y')); #else - hasMultiResultSets = QString::fromLocal8Bit(driverResponse, length).startsWith(QLatin1Char('Y')); + hasMultiResultSets = QString::fromUtf8((const char *)driverResponse.constData(), length).startsWith(QLatin1Char('Y')); #endif } @@ -2114,9 +2166,9 @@ QStringList QODBCDriver::tables(QSql::TableType type) const NULL, 0, #ifdef UNICODE - (SQLWCHAR*)joinedTableTypeString.unicode(), + toSQLTCHAR(joinedTableTypeString).data(), #else - (SQLCHAR*)joinedTableTypeString.toLatin1().constData(), + (SQLCHAR*)joinedTableTypeString.toUtf8().data(), #endif joinedTableTypeString.length() /* characters, not bytes */); @@ -2130,6 +2182,11 @@ QStringList QODBCDriver::tables(QSql::TableType type) const else r = SQLFetch(hStmt); + if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO && r != SQL_NO_DATA) { + qWarning() << "QODBCDriver::tables failed to retrieve table/view list: (" << r << "," << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ")"; + return QStringList(); + } + while (r == SQL_SUCCESS) { QString fieldVal = qGetStringData(hStmt, 2, -1, false); tl.append(fieldVal); @@ -2188,21 +2245,21 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const SQL_IS_UINTEGER); r = SQLPrimaryKeys(hStmt, #ifdef UNICODE - catalog.length() == 0 ? NULL : (SQLWCHAR*)catalog.unicode(), + catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), #else - catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toLatin1().constData(), + catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toUtf8().data(), #endif catalog.length(), #ifdef UNICODE - schema.length() == 0 ? NULL : (SQLWCHAR*)schema.unicode(), + schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), #else - schema.length() == 0 ? NULL : (SQLCHAR*)schema.toLatin1().constData(), + schema.length() == 0 ? NULL : (SQLCHAR*)schema.toUtf8().data(), #endif schema.length(), #ifdef UNICODE - (SQLWCHAR*)table.unicode(), + toSQLTCHAR(table).data(), #else - (SQLCHAR*)table.toLatin1().constData(), + (SQLCHAR*)table.toUtf8().data(), #endif table.length() /* in characters, not in bytes */); @@ -2213,21 +2270,21 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const r = SQLSpecialColumns(hStmt, SQL_BEST_ROWID, #ifdef UNICODE - catalog.length() == 0 ? NULL : (SQLWCHAR*)catalog.unicode(), + catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), #else - catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toLatin1().constData(), + catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toUtf8().data(), #endif catalog.length(), #ifdef UNICODE - schema.length() == 0 ? NULL : (SQLWCHAR*)schema.unicode(), + schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), #else - schema.length() == 0 ? NULL : (SQLCHAR*)schema.toLatin1().constData(), + schema.length() == 0 ? NULL : (SQLCHAR*)schema.toUtf8().data(), #endif schema.length(), #ifdef UNICODE - (SQLWCHAR*)table.unicode(), + toSQLTCHAR(table).data(), #else - (SQLCHAR*)table.toLatin1().constData(), + (SQLCHAR*)table.toUtf8().data(), #endif table.length(), SQL_SCOPE_CURROW, @@ -2313,21 +2370,21 @@ QSqlRecord QODBCDriver::record(const QString& tablename) const SQL_IS_UINTEGER); r = SQLColumns(hStmt, #ifdef UNICODE - catalog.length() == 0 ? NULL : (SQLWCHAR*)catalog.unicode(), + catalog.length() == 0 ? NULL : toSQLTCHAR(catalog).data(), #else - catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toLatin1().constData(), + catalog.length() == 0 ? NULL : (SQLCHAR*)catalog.toUtf8().data(), #endif catalog.length(), #ifdef UNICODE - schema.length() == 0 ? NULL : (SQLWCHAR*)schema.unicode(), + schema.length() == 0 ? NULL : toSQLTCHAR(schema).data(), #else - schema.length() == 0 ? NULL : (SQLCHAR*)schema.toLatin1().constData(), + schema.length() == 0 ? NULL : (SQLCHAR*)schema.toUtf8().data(), #endif schema.length(), #ifdef UNICODE - (SQLWCHAR*)table.unicode(), + toSQLTCHAR(table).data(), #else - (SQLCHAR*)table.toLatin1().constData(), + (SQLCHAR*)table.toUtf8().data(), #endif table.length(), NULL, diff --git a/src/sql/drivers/odbc/qsql_odbc.h b/src/sql/drivers/odbc/qsql_odbc.h index 836dbd6..e739a38 100644 --- a/src/sql/drivers/odbc/qsql_odbc.h +++ b/src/sql/drivers/odbc/qsql_odbc.h @@ -68,7 +68,6 @@ # undef _MSC_VER #endif -#include <sqlucode.h> #include <sqlext.h> QT_BEGIN_HEADER diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 6c6436f..f253c82 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -822,6 +822,9 @@ bool QSqlQuery::isForwardOnly() const scrollable. isForwardOnly() will always return the correct status of the result set. + \note Calling setForwardOnly after execution of the query will result + in unexpected results at best, and crashes at worst. + \sa isForwardOnly(), next(), seek(), QSqlResult::setForwardOnly() */ void QSqlQuery::setForwardOnly(bool forward) @@ -999,10 +1002,18 @@ bool QSqlQuery::execBatch(BatchExecutionMode mode) must be included when specifying the placeholder name. If \a paramType is QSql::Out or QSql::InOut, the placeholder will be overwritten with data from the database after the exec() call. + In this case, sufficient space must be pre-allocated to store + the result into. To bind a NULL value, use a null QVariant; for example, use \c {QVariant(QVariant::String)} if you are binding a string. + Values cannot be bound to multiple locations in the query, eg: + \code + INSERT INTO testtable (id, name, samename) VALUES (:id, :name, :name) + \endcode + Binding to name will bind to the first :name, but not the second. + \sa addBindValue(), prepare(), exec(), boundValue() boundValues() */ void QSqlQuery::bindValue(const QString& placeholder, const QVariant& val, diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index 3d63f88..6382b42 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -564,6 +564,9 @@ bool QSqlResult::isForwardOnly() const scrollable. isForwardOnly() will always return the correct status of the result set. + \note Calling setForwardOnly after execution of the query will result + in unexpected results at best, and crashes at worst. + \sa isForwardOnly(), fetchNext(), QSqlQuery::setForwardOnly() */ void QSqlResult::setForwardOnly(bool forward) @@ -707,7 +710,15 @@ void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType param Binds the value \a val of parameter type \a paramType to the \a placeholder name in the current record (row). - Note that binding an undefined placeholder will result in undefined behavior. + Values cannot be bound to multiple locations in the query, eg: + \code + INSERT INTO testtable (id, name, samename) VALUES (:id, :name, :name) + \endcode + Binding to name will bind to the first :name, but not the second. + + \note Binding an undefined placeholder will result in undefined behavior. + + \sa QSqlQuery::bindValue() */ void QSqlResult::bindValue(const QString& placeholder, const QVariant& val, QSql::ParamType paramType) diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 8d9ae4f..0150515 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -3487,6 +3487,7 @@ QDomDocumentTypePrivate::QDomDocumentTypePrivate(QDomDocumentTypePrivate* n, boo if (p->isNotation()) // Dont use normal insert function since we would create infinite recursion notations->map.insertMulti(p->nodeName(), p); + p = p->next; } } |