diff options
author | Tor Arne Vestbø <tor.arne.vestbo@digia.com> | 2012-10-19 09:53:42 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@digia.com> | 2012-10-19 09:54:12 +0200 |
commit | 55a36aed7935984846db2342e37160057cb3bec8 (patch) | |
tree | b84f611333fe9ec6ecda62c9ea47f954f59bc394 /src | |
parent | a9a87deb685600aebd9ed1cec82ad668afca88d9 (diff) | |
parent | 734324c37cb9d8417aa86f76fc81dadc21be2156 (diff) |
Merge remote-tracking branch 'gerrit/master' into newdocs
Change-Id: If7f46d56cf0b0b79f7fc8955a01964121b900d07
Diffstat (limited to 'src')
143 files changed, 6233 insertions, 1873 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp b/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp index 662ce35054..34c81189c1 100644 --- a/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_plugin_quuid.cpp @@ -40,5 +40,5 @@ //! [0] // {67C8770B-44F1-410A-AB9A-F9B5446F13EE} -QUuid IID_MyInterface(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee) +QUuid IID_MyInterface(0x67c8770b, 0x44f1, 0x410a, 0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee); //! [0] diff --git a/src/corelib/doc/snippets/pointer/pointer.cpp b/src/corelib/doc/snippets/pointer/pointer.cpp index 31b4959651..503f2dfccd 100644 --- a/src/corelib/doc/snippets/pointer/pointer.cpp +++ b/src/corelib/doc/snippets/pointer/pointer.cpp @@ -53,7 +53,8 @@ int main(int argc, char *argv[]) //! [1] if (label) -//! [1] //! [2] +//! [1] +//! [2] label->show(); //! [2] return 0; diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 05a2461f1b..01756c8419 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -9,6 +9,7 @@ HEADERS += \ global/qendian.h \ global/qnumeric_p.h \ global/qnumeric.h \ + global/qlibraryinfo.h \ global/qlogging.h \ global/qtypeinfo.h \ global/qsysinfo.h \ diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 13bbdbead0..e4ff7eece4 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -780,6 +780,12 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont return message; } +#if !QT_DEPRECATED_SINCE(5, 0) +// make sure they're defined to be exported +typedef void (*QtMsgHandler)(QtMsgType, const char *); +Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); +#endif + static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context) static QtMessageHandler messageHandler = 0; // pointer to debug handler (with context) diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h index 0c92e71ad6..4a4eb26321 100644 --- a/src/corelib/global/qlogging.h +++ b/src/corelib/global/qlogging.h @@ -161,9 +161,10 @@ Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &contex Q_CORE_EXPORT void qErrnoWarning(int code, const char *msg, ...); Q_CORE_EXPORT void qErrnoWarning(const char *msg, ...); -// deprecated. Use qInstallMessageHandler instead! +#if QT_DEPRECATED_SINCE(5, 0)// deprecated. Use qInstallMessageHandler instead! typedef void (*QtMsgHandler)(QtMsgType, const char *); -Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); +Q_CORE_EXPORT QT_DEPRECATED QtMsgHandler qInstallMsgHandler(QtMsgHandler); +#endif typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &); Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler); diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index 74bc0e6a9d..4b9391d285 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -853,12 +853,18 @@ static QItemSelection mergeIndexes(const QVector<QPersistentModelIndex> &indexes int i = 0; while (i < indexes.count()) { const QPersistentModelIndex &tl = indexes.at(i); + if (!tl.isValid()) { + ++i; + continue; + } QPersistentModelIndex br = tl; QModelIndex brParent = br.parent(); int brRow = br.row(); int brColumn = br.column(); while (++i < indexes.count()) { const QPersistentModelIndex &next = indexes.at(i); + if (!next.isValid()) + continue; const QModelIndex nextParent = next.parent(); const int nextRow = next.row(); const int nextColumn = next.column(); diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp index 33ca1023dd..b2ec574c89 100644 --- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp +++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp @@ -243,28 +243,6 @@ void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notif } } -static inline bool updateTimeout(int *timeout, const struct timeval &start) -{ - // A timeout of -1 means we should block indefinitely. If we get here, we got woken up by a - // non-IO BPS event, and that event has been processed already. This means we can go back and - // block in bps_get_event(). - // Note that processing the BPS event might have triggered a wakeup, in that case we get a - // IO event in the next bps_get_event() right away. - if (*timeout == -1) - return true; - - if (Q_UNLIKELY(!QElapsedTimer::isMonotonic())) { - // we cannot recalculate the timeout without a monotonic clock as the time may have changed - return false; - } - - // clock source is monotonic, so we can recalculate how much timeout is left - timeval t2 = qt_gettime(); - int elapsed = (t2.tv_sec * 1000 + t2.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); - *timeout -= elapsed; - return *timeout >= 0; -} - int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout) { @@ -291,60 +269,70 @@ int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writef FD_ZERO(exceptfds); // Convert timeout to milliseconds - int timeout_bps = -1; + int timeoutTotal = -1; if (timeout) - timeout_bps = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + timeoutTotal = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + + int timeoutLeft = timeoutTotal; - bool hasProcessedEventsOnce = false; bps_event_t *event = 0; + unsigned int eventCount = 0; // This loop exists such that we can drain the bps event queue of all native events // more efficiently than if we were to return control to Qt after each event. This // is important for handling touch events which can come in rapidly. forever { - Q_ASSERT(!hasProcessedEventsOnce || event); - - // Only emit the awake() and aboutToBlock() signals in the second iteration. For the first - // iteration, the UNIX event dispatcher will have taken care of that already. - if (hasProcessedEventsOnce) - emit awake(); - - // Filtering the native event should happen between the awake() and aboutToBlock() signal - // emissions. The calls awake() - filterNativeEvent() - aboutToBlock() - bps_get_event() - // need not to be interrupted by a break or return statement. - // - // Because of this, the native event is actually processed one loop iteration - // after it was retrieved with bps_get_event(). - if (event) - filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); - - if (hasProcessedEventsOnce) - emit aboutToBlock(); + // Only emit the awake() and aboutToBlock() signals in the second iteration. For the + // first iteration, the UNIX event dispatcher will have taken care of that already. + // Also native events are actually processed one loop iteration after they were + // retrieved with bps_get_event(). + + // Filtering the native event should happen between the awake() and aboutToBlock() + // signal emissions. The calls awake() - filterNativeEvent() - aboutToBlock() - + // bps_get_event() need not to be interrupted by a break or return statement. + if (eventCount > 0) { + if (event) { + emit awake(); + filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); + emit aboutToBlock(); + } + + // Update the timeout + // Clock source is monotonic, so we can recalculate how much timeout is left + if (timeoutTotal != -1) { + timeval t2 = qt_gettime(); + timeoutLeft = timeoutTotal - ((t2.tv_sec * 1000 + t2.tv_usec / 1000) + - (startTime.tv_sec * 1000 + startTime.tv_usec / 1000)); + if (timeoutLeft < 0) + timeoutLeft = 0; + } + } // Wait for event or file to be ready event = 0; - const int result = bps_get_event(&event, timeout_bps); + const int result = bps_get_event(&event, timeoutLeft); if (result != BPS_SUCCESS) qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed"); - // In the case of !event, we break out of the loop to let Qt process the timers - // that are now ready (since timeout has expired). - // In the case of bpsIOReadyDomain, we break out to let Qt process the FDs that - // are ready. If we do not do this activation of QSocketNotifiers etc would be - // delayed. - if (!event || bps_event_get_domain(event) == bpsIOReadyDomain) - break; + if (!event) // In case of !event, we break out of the loop to let Qt process the timers + break; // (since timeout has expired) and socket notifiers that are now ready. - // Update the timeout. If this fails we have exceeded our alloted time or the system - // clock has changed time and we cannot calculate a new timeout so we bail out. - if (!updateTimeout(&timeout_bps, startTime)) { + if (bps_event_get_domain(event) == bpsIOReadyDomain) { + timeoutTotal = 0; // in order to immediately drain the event queue of native events + event = 0; // (especially touch move events) we don't break out here + } + + ++eventCount; - // No more loop iteration, so we need to filter the event here. - filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); + // Make sure we are not trapped in this loop due to continuous native events + // also we cannot recalculate the timeout without a monotonic clock as the time may have changed + const unsigned int maximumEventCount = 12; + if (Q_UNLIKELY((eventCount > maximumEventCount && timeoutLeft == 0) + || !QElapsedTimer::isMonotonic())) { + if (event) + filterNativeEvent(QByteArrayLiteral("bps_event_t"), static_cast<void*>(event), 0); break; } - - hasProcessedEventsOnce = true; } // the number of bits set in the file sets diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp index 48710bb70c..b774b36592 100644 --- a/src/corelib/kernel/qpointer.cpp +++ b/src/corelib/kernel/qpointer.cpp @@ -123,7 +123,7 @@ /*! \fn QPointer::QPointer(T* p) - Constructs a guarded pointer that points to same object that \a p + Constructs a guarded pointer that points to the same object that \a p points to. */ @@ -273,3 +273,11 @@ \a p2 are not pointing to the same object, otherwise returns false. */ +/*! + \fn QPointer<T> qPointerFromVariant(const QVariant &variant) + + \internal + + Returns a guarded pointer that points to the same object that + \a variant holds. +*/ diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 6d9133529a..c4486d3ae6 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -695,7 +695,7 @@ static QString find_translation(const QLocale & locale, \li File name with ui language part stripped further, etc. \endlist - For example, an application running in the locale with the following + For example, an application running in the \a locale with the following \l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call load(QLocale::system(), "foo", ".", "/opt/foolib", ".qm"). load() would replace '-' (dash) with '_' (underscore) in the ui language and then try to diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 445f707a73..c1ebc57cf6 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -181,7 +181,7 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto are in use. Each UUID contains a bit field that specifies which type (variant) of UUID it is. Call variant() to discover which type of UUID an instance of QUuid contains. It extracts the three - most signifcant bits of byte 8 of the 16 bytes. In QUuid, byte 8 + most significant bits of byte 8 of the 16 bytes. In QUuid, byte 8 is \c{QUuid::data4[0]}. If you create instances of QUuid using the constructor that accepts all the numeric values as parameters, use the following table to set the three most significant bits of @@ -428,7 +428,17 @@ QUuid::QUuid(const QByteArray &text) \since 5.0 \fn QUuid QUuid::createUuidV3(const QUuid &ns, const QByteArray &baseData); - This functions returns a new UUID with variant QUuid::DCE and version QUuid::Md5. + This function returns a new UUID with variant QUuid::DCE and version QUuid::Md5. + \a ns is the namespace and \a baseData is the basic data as described by RFC 4122. + + \sa variant(), version(), createUuidV5() +*/ + +/*! + \since 5.0 + \fn QUuid QUuid::createUuidV3(const QUuid &ns, const QString &baseData); + + This function returns a new UUID with variant QUuid::DCE and version QUuid::Md5. \a ns is the namespace and \a baseData is the basic data as described by RFC 4122. \sa variant(), version(), createUuidV5() @@ -438,7 +448,17 @@ QUuid::QUuid(const QByteArray &text) \since 5.0 \fn QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData); - This functions returns a new UUID with variant QUuid::DCE and version QUuid::Sha1. + This function returns a new UUID with variant QUuid::DCE and version QUuid::Sha1. + \a ns is the namespace and \a baseData is the basic data as described by RFC 4122. + + \sa variant(), version(), createUuidV3() +*/ + +/*! + \since 5.0 + \fn QUuid QUuid::createUuidV5(const QUuid &ns, const QString &baseData); + + This function returns a new UUID with variant QUuid::DCE and version QUuid::Sha1. \a ns is the namespace and \a baseData is the basic data as described by RFC 4122. \sa variant(), version(), createUuidV3() @@ -990,6 +1010,10 @@ QUuid QUuid::createUuid() */ #ifndef QT_NO_DEBUG_STREAM +/*! + \relates QUuid + Writes the UUID \a id to the output stream for debugging information \a dbg. +*/ QDebug operator<<(QDebug dbg, const QUuid &id) { #ifndef QT_NO_QUUID_STRING diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h index 3314cd7aaf..d084e24c0c 100644 --- a/src/corelib/thread/qresultstore.h +++ b/src/corelib/thread/qresultstore.h @@ -176,7 +176,10 @@ public: int addResults(int index, const QVector<T> *results, int totalCount) { - return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), totalCount); + if (m_filterMode == true && results->count() != totalCount && 0 == results->count()) + return ResultStoreBase::addResults(index, 0, 0, totalCount); + else + return ResultStoreBase::addResults(index, new QVector<T>(*results), results->count(), totalCount); } int addCanceledResult(int index) diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index a67255ad68..7fecbbbeeb 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -209,12 +209,12 @@ struct QTypedArrayData T *data() { return static_cast<T *>(QArrayData::data()); } const T *data() const { return static_cast<const T *>(QArrayData::data()); } - iterator begin() { return data(); } - iterator end() { return data() + size; } - const_iterator begin() const { return data(); } - const_iterator end() const { return data() + size; } - const_iterator constBegin() const { return data(); } - const_iterator constEnd() const { return data() + size; } + iterator begin(iterator = iterator()) { return data(); } + iterator end(iterator = iterator()) { return data() + size; } + const_iterator begin(const_iterator = const_iterator()) const { return data(); } + const_iterator end(const_iterator = const_iterator()) const { return data() + size; } + const_iterator constBegin(const_iterator = const_iterator()) const { return data(); } + const_iterator constEnd(const_iterator = const_iterator()) const { return data() + size; } class AlignmentDummy { QArrayData header; T data; }; diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 0a027fc229..c66962d931 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -121,7 +121,7 @@ QT_BEGIN_NAMESPACE isDigit() (decimal digits). All of these are wrappers around category() which return the Unicode-defined category of each character. Some of these also calculate the derived properties - (i.e. isSpace() returns true if the character is of category + (for example isSpace() returns true if the character is of category Separator_* or an exceptional code point from Other_Control category). QChar also provides direction(), which indicates the "natural" @@ -766,14 +766,14 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) \fn bool QChar::isHighSurrogate() const Returns true if the QChar is the high part of a UTF16 surrogate - (i.e. if its code point is in range [0xd800..0xdbff]); false otherwise. + (for example if its code point is in range [0xd800..0xdbff]); false otherwise. */ /*! \fn bool QChar::isLowSurrogate() const Returns true if the QChar is the low part of a UTF16 surrogate - (i.e. if its code point is in range [0xdc00..0xdfff]); false otherwise. + (for example if its code point is in range [0xdc00..0xdfff]); false otherwise. */ /*! @@ -782,7 +782,7 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Returns true if the QChar contains a code point that is in either the high or the low part of the UTF-16 surrogate range - (i.e. if its code point is in range [0xd800..0xdfff]); false otherwise. + (for example if its code point is in range [0xd800..0xdfff]); false otherwise. */ /*! @@ -806,7 +806,7 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Returns true if the UCS-4-encoded character specified by \a ucs4 is the high part of a UTF16 surrogate - (i.e. if its code point is in range [0xd800..0xdbff]); false otherwise. + (for example if its code point is in range [0xd800..0xdbff]); false otherwise. */ /*! @@ -815,7 +815,7 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Returns true if the UCS-4-encoded character specified by \a ucs4 is the low part of a UTF16 surrogate - (i.e. if its code point is in range [0xdc00..0xdfff]); false otherwise. + (for example if its code point is in range [0xdc00..0xdfff]); false otherwise. */ /*! @@ -825,7 +825,7 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Returns true if the UCS-4-encoded character specified by \a ucs4 contains a code point that is in either the high or the low part of the - UTF-16 surrogate range (i.e. if its code point is in range [0xd800..0xdfff]); + UTF-16 surrogate range (for example if its code point is in range [0xd800..0xdfff]); false otherwise. */ @@ -834,7 +834,7 @@ bool QT_FASTCALL QChar::isLetterOrNumber_helper(uint ucs4) Returns true if the UCS-4-encoded character specified by \a ucs4 can be split into the high and low parts of a UTF16 surrogate - (i.e. if its code point is greater than or equals to 0x10000); + (for example if its code point is greater than or equals to 0x10000); false otherwise. */ @@ -969,31 +969,63 @@ bool QChar::hasMirrored(uint ucs4) /*! \fn bool QChar::isLower() const - Returns true if the character is a lowercase letter, i.e. + Returns true if the character is a lowercase letter, for example category() is Letter_Lowercase. \sa isUpper(), toLower(), toUpper() */ /*! + \fn static bool QChar::isLower(uint ucs4) + \overload + \since 5.0 + + Returns true if the UCS-4-encoded character specified by \a ucs4 + is a lowercase letter, for example category() is Letter_Lowercase. + + \sa isUpper(), toLower(), toUpper() +*/ + +/*! \fn bool QChar::isUpper() const - Returns true if the character is an uppercase letter, i.e. + Returns true if the character is an uppercase letter, for example category() is Letter_Uppercase. \sa isLower(), toUpper(), toLower() */ /*! + \fn static bool QChar::isUpper(uint ucs4) + \overload + \since 5.0 + + Returns true if the UCS-4-encoded character specified by \a ucs4 + is an uppercase letter, for example category() is Letter_Uppercase. + + \sa isLower(), toUpper(), toLower() +*/ + +/*! \fn bool QChar::isTitleCase() const - Returns true if the character is a titlecase letter, i.e. + Returns true if the character is a titlecase letter, for example category() is Letter_Titlecase. \sa isLower(), toUpper(), toLower(), toTitleCase() */ /*! + \fn static bool QChar::isTitleCase(uint ucs4) + \overload + \since 5.0 + + Returns true if the UCS-4-encoded character specified by \a ucs4 + is a titlecase letter, for example category() is Letter_Titlecase. + + \sa isLower(), toUpper(), toLower(), toTitleCase() +*/ +/*! \fn QChar QChar::mirroredChar() const Returns the mirrored character if this character is a mirrored diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp index 3e325bec59..40edb0fa58 100644 --- a/src/corelib/tools/qcontiguouscache.cpp +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -80,8 +80,15 @@ void QContiguousCacheData::freeData(QContiguousCacheData *data) of matching how user interface views most commonly request data, as a set of rows localized around the current scrolled position. This restriction allows the cache to consume less memory and processor - cycles than QCache. The QContiguousCache class also can provide - an upper bound on memory usage via setCapacity(). + cycles than QCache. + + QContiguousCache operates on a fixed capacity, set with setCapacity() or + passed as a parameter to the constructor. This capacity is the upper bound + on memory usage by the cache itself, not including the memory allocated by + the elements themselves. Note that a cache with a capacity of zero (the + default) means no items will be stored: the insert(), append() and + prepend() operations will effectively be no-ops. Therefore, it's important + to set the capacity to a reasonable value before adding items to the cache. The simplest way of using a contiguous cache is to use the append() and prepend(). diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 8713a3407a..e1cc65f10a 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -341,6 +341,8 @@ void QContiguousCache<T>::freeData(Data *x) template <typename T> void QContiguousCache<T>::append(const T &value) { + if (!d->alloc) + return; // zero capacity detach(); if (QTypeInfo<T>::isComplex) { if (d->count == d->alloc) @@ -362,6 +364,8 @@ void QContiguousCache<T>::append(const T &value) template<typename T> void QContiguousCache<T>::prepend(const T &value) { + if (!d->alloc) + return; // zero capacity detach(); if (d->start) d->start--; @@ -385,6 +389,8 @@ template<typename T> void QContiguousCache<T>::insert(int pos, const T &value) { Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range"); + if (!d->alloc) + return; // zero capacity detach(); if (containsIndex(pos)) { if (QTypeInfo<T>::isComplex) { diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index cbdd183f33..a9d3095224 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -847,6 +847,7 @@ QString QDate::toString(const QString& format) const If \a y is in the range 0 to 99, it is interpreted as 1900 to 1999. + Returns \c false if the date is invalid. Use setDate() instead. */ diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 5436d1f94a..5c6b3ff044 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -2345,7 +2345,9 @@ static const char *pcreCompileErrorCodes[] = QT_TRANSLATE_NOOP("QRegularExpression", "\\N is not supported in a class"), QT_TRANSLATE_NOOP("QRegularExpression", "too many forward references"), QT_TRANSLATE_NOOP("QRegularExpression", "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)"), - QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-16 string") + QT_TRANSLATE_NOOP("QRegularExpression", "invalid UTF-16 string"), + QT_TRANSLATE_NOOP("QRegularExpression", "name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)"), + QT_TRANSLATE_NOOP("QRegularExpression", "character value in \\u.... sequence is too large") }; #endif // #if 0 diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index c0ae048322..925ad17110 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -151,6 +151,7 @@ public: // STL-style typedef typename Data::iterator iterator; typedef typename Data::const_iterator const_iterator; +#if !defined(QT_STRICT_ITERATORS) || defined(Q_QDOC) inline iterator begin() { detach(); return d->begin(); } inline const_iterator begin() const { return d->constBegin(); } inline const_iterator cbegin() const { return d->constBegin(); } @@ -159,6 +160,16 @@ public: inline const_iterator end() const { return d->constEnd(); } inline const_iterator cend() const { return d->constEnd(); } inline const_iterator constEnd() const { return d->constEnd(); } +#else + inline iterator begin(iterator = iterator()) { detach(); return d->begin(); } + inline const_iterator begin(const_iterator = const_iterator()) const { return d->constBegin(); } + inline const_iterator cbegin(const_iterator = const_iterator()) const { return d->constBegin(); } + inline const_iterator constBegin(const_iterator = const_iterator()) const { return d->constBegin(); } + inline iterator end(iterator = iterator()) { detach(); return d->end(); } + inline const_iterator end(const_iterator = const_iterator()) const { return d->constEnd(); } + inline const_iterator cend(const_iterator = const_iterator()) const { return d->constEnd(); } + inline const_iterator constEnd(const_iterator = const_iterator()) const { return d->constEnd(); } +#endif iterator insert(iterator before, int n, const T &x); inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); } iterator erase(iterator begin, iterator end); diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h index a6e58e9148..f51728b47b 100644 --- a/src/dbus/qdbus_symbols_p.h +++ b/src/dbus/qdbus_symbols_p.h @@ -297,10 +297,6 @@ DEFINEFUNC(void , dbus_message_unref, (DBusMessage *message), (message), ) /* dbus-misc.h */ -DEFINEFUNC(void , dbus_get_version , (int *major_version_p, - int *minor_version_p, - int *micro_version_p), - (major_version_p, minor_version_p, micro_version_p), ) DEFINEFUNC(char* , dbus_get_local_machine_id , (void), (), return) @@ -363,14 +359,6 @@ DEFINEFUNC(void , dbus_server_unref, (DBusServer *server), /* dbus-thread.h */ DEFINEFUNC(dbus_bool_t , dbus_threads_init_default, (), (), return) - -/* D-Bus 1.4 symbols */ -#if !defined(QT_LINKED_LIBDBUS) || (DBUS_VERSION >= 0x010400) -DEFINEFUNC(dbus_bool_t , dbus_connection_can_send_type , (DBusConnection *connection, - int type), - (connection, type), return) -#endif - QT_END_NAMESPACE #endif // QT_NO_DBUS diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index a6d4017a2d..2b3ee901a5 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -112,7 +112,7 @@ static inline QDebug operator<<(QDebug dbg, const QDBusConnectionPrivate *conn) return dbg.space(); } -Q_AUTOTEST_EXPORT void qdbusDefaultThreadDebug(int action, int condition, QDBusConnectionPrivate *conn) +void qdbusDefaultThreadDebug(int action, int condition, QDBusConnectionPrivate *conn) { qDBusDebug() << QThread::currentThread() << "QtDBus threading action" << action @@ -131,7 +131,7 @@ Q_AUTOTEST_EXPORT void qdbusDefaultThreadDebug(int action, int condition, QDBusC "condition unknown") << "in connection" << conn; } -Q_AUTOTEST_EXPORT qdbusThreadDebugFunc qdbusThreadDebug = 0; +qdbusThreadDebugFunc qdbusThreadDebug = 0; #endif typedef void (*QDBusSpyHook)(const QDBusMessage&); @@ -1687,24 +1687,23 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnection *connection) { QDBusConnection::ConnectionCapabilities result = 0; + typedef dbus_bool_t (*can_send_type_t)(DBusConnection *, int); + static can_send_type_t can_send_type = 0; -#if defined(QT_LINKED_LIBDBUS) && DBUS_VERSION < 0x010400 - // no capabilities are possible +#if defined(QT_LINKED_LIBDBUS) +# if DBUS_VERSION-0 >= 0x010400 + can_send_type = dbus_connection_can_send_type; +# endif #else -# if !defined(QT_LINKED_LIBDBUS) // run-time check if the next functions are available - int major, minor, micro; - q_dbus_get_version(&major, &minor, µ); - if (major == 1 && minor < 4) - return result; -# endif + can_send_type = (can_send_type_t)qdbus_resolve_conditionally("dbus_connection_can_send_type"); +#endif #ifndef DBUS_TYPE_UNIX_FD # define DBUS_TYPE_UNIX_FD int('h') #endif - if (q_dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD)) + if (can_send_type && can_send_type(connection, DBUS_TYPE_UNIX_FD)) result |= QDBusConnection::UnixFileDescriptorPassing; -#endif return result; } diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h index c1e7b8b5a2..e93324b4f8 100644 --- a/src/gui/accessible/qaccessible2.h +++ b/src/gui/accessible/qaccessible2.h @@ -52,8 +52,6 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY -class QModelIndex; - namespace QAccessible2 { enum BoundaryType { diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp index 1c2a6d301b..ff93801524 100644 --- a/src/gui/kernel/qdrag.cpp +++ b/src/gui/kernel/qdrag.cpp @@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE /*! \class QDrag \inmodule QtGui + \ingroup draganddrop \brief The QDrag class provides support for MIME-based drag and drop data transfer. diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index b91d3d0281..2e896eecf4 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -43,6 +43,7 @@ #include <QtCore/QVariant> #include <QtCore/QStringList> +#include <QtCore/qfileinfo.h> #include <qpalette.h> #include <qtextformat.h> @@ -164,6 +165,22 @@ const QFont *QPlatformTheme::font(Font type) const return 0; } +QPixmap QPlatformTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const +{ + Q_UNUSED(sp); + Q_UNUSED(size); + // TODO Should return QCommonStyle pixmaps? + return QPixmap(); +} + +QPixmap QPlatformTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const +{ + Q_UNUSED(fileInfo); + Q_UNUSED(size); + // TODO Should return QCommonStyle pixmaps? + return QPixmap(); +} + QVariant QPlatformTheme::themeHint(ThemeHint hint) const { return QPlatformTheme::defaultThemeHint(hint); @@ -223,6 +240,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint) return QVariant(int(QTextCharFormat::SpellCheckUnderline)); case TabAllWidgets: return QVariant(true); + case IconPixmapSizes: + return QVariant::fromValue(QList<int>()); } return QVariant(); } diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index 398339255c..25453e792f 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -67,6 +67,9 @@ class QPlatformSystemTrayIcon; class QVariant; class QPalette; class QFont; +class QPixmap; +class QSizeF; +class QFileInfo; class Q_GUI_EXPORT QPlatformTheme { @@ -97,7 +100,8 @@ public: KeyboardScheme, UiEffects, SpellCheckUnderlineStyle, - TabAllWidgets + TabAllWidgets, + IconPixmapSizes }; enum DialogType { @@ -150,6 +154,81 @@ public: NFonts }; + enum StandardPixmap { // Keep in sync with QStyle::StandardPixmap + TitleBarMenuButton, + TitleBarMinButton, + TitleBarMaxButton, + TitleBarCloseButton, + TitleBarNormalButton, + TitleBarShadeButton, + TitleBarUnshadeButton, + TitleBarContextHelpButton, + DockWidgetCloseButton, + MessageBoxInformation, + MessageBoxWarning, + MessageBoxCritical, + MessageBoxQuestion, + DesktopIcon, + TrashIcon, + ComputerIcon, + DriveFDIcon, + DriveHDIcon, + DriveCDIcon, + DriveDVDIcon, + DriveNetIcon, + DirOpenIcon, + DirClosedIcon, + DirLinkIcon, + DirLinkOpenIcon, + FileIcon, + FileLinkIcon, + ToolBarHorizontalExtensionButton, + ToolBarVerticalExtensionButton, + FileDialogStart, + FileDialogEnd, + FileDialogToParent, + FileDialogNewFolder, + FileDialogDetailedView, + FileDialogInfoView, + FileDialogContentsView, + FileDialogListView, + FileDialogBack, + DirIcon, + DialogOkButton, + DialogCancelButton, + DialogHelpButton, + DialogOpenButton, + DialogSaveButton, + DialogCloseButton, + DialogApplyButton, + DialogResetButton, + DialogDiscardButton, + DialogYesButton, + DialogNoButton, + ArrowUp, + ArrowDown, + ArrowLeft, + ArrowRight, + ArrowBack, + ArrowForward, + DirHomeIcon, + CommandLink, + VistaShield, + BrowserReload, + BrowserStop, + MediaPlay, + MediaStop, + MediaPause, + MediaSkipForward, + MediaSkipBackward, + MediaSeekForward, + MediaSeekBackward, + MediaVolume, + MediaVolumeMuted, + // do not add any values below/greater than this + CustomBase = 0xf0000000 + }; + enum KeyboardSchemes { WindowsKeyboardScheme, @@ -190,6 +269,9 @@ public: virtual QVariant themeHint(ThemeHint hint) const; + virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const; + virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const; + static QVariant defaultThemeHint(ThemeHint hint); }; diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 27dfd7cf40..2bc6b01b3e 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -213,13 +213,12 @@ QPoint QPlatformWindow::mapFromGlobal(const QPoint &pos) const /*! Requests setting the window state of this surface - to \a type. Returns the actual state set. + to \a type. Qt::WindowActive can be ignored. */ -Qt::WindowState QPlatformWindow::setWindowState(Qt::WindowState) +void QPlatformWindow::setWindowState(Qt::WindowState) { - return Qt::WindowNoState; } /*! diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h index 2b2d227fcf..12650d6073 100644 --- a/src/gui/kernel/qplatformwindow.h +++ b/src/gui/kernel/qplatformwindow.h @@ -91,7 +91,7 @@ public: virtual void setVisible(bool visible); virtual void setWindowFlags(Qt::WindowFlags flags); - virtual Qt::WindowState setWindowState(Qt::WindowState state); + virtual void setWindowState(Qt::WindowState state); virtual WId winId() const; virtual void setParent(const QPlatformWindow *window); diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 27e1571184..4f1610cb21 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -286,6 +286,10 @@ void QWindow::setVisible(bool visible) QGuiApplicationPrivate::hideModalWindow(this); } +#ifndef QT_NO_CURSOR + if (visible) + d->applyCursor(); +#endif d->platformWindow->setVisible(visible); if (!visible) { @@ -824,9 +828,8 @@ void QWindow::setWindowState(Qt::WindowState state) Q_D(QWindow); if (d->platformWindow) - d->windowState = d->platformWindow->setWindowState(state); - else - d->windowState = state; + d->platformWindow->setWindowState(state); + d->windowState = state; } /*! @@ -1853,11 +1856,10 @@ QCursor QWindow::cursor() const void QWindow::setCursor(const QCursor &cursor) { Q_D(QWindow); - if (QPlatformCursor *platformCursor = d->screen->handle()->cursor()) { - d->cursor = cursor; - QCursor *oc = QGuiApplication::overrideCursor(); - QCursor c = oc ? *oc : d->cursor; - platformCursor->changeCursor(&c, this); + d->cursor = cursor; + // Only attempt to set cursor and emit signal if there is an actual platform cursor + if (d->screen->handle()->cursor()) { + d->applyCursor(); QEvent event(QEvent::CursorChange); QGuiApplication::sendEvent(this, &event); } @@ -1868,19 +1870,20 @@ void QWindow::setCursor(const QCursor &cursor) */ void QWindow::unsetCursor() { - Q_D(QWindow); - if (QPlatformCursor *platformCursor = d->screen->handle()->cursor()) { - d->cursor = Qt::ArrowCursor; - QCursor *oc = QGuiApplication::overrideCursor(); - if (!oc) { - QCursor c = d->cursor; - platformCursor->changeCursor(&c, this); + setCursor(Qt::ArrowCursor); +} + +void QWindowPrivate::applyCursor() +{ + Q_Q(QWindow); + if (platformWindow) { + if (QPlatformCursor *platformCursor = screen->handle()->cursor()) { + QCursor *oc = QGuiApplication::overrideCursor(); + QCursor c = oc ? *oc : cursor; + platformCursor->changeCursor(&c, q); } - QEvent event(QEvent::CursorChange); - QGuiApplication::sendEvent(this, &event); } } - #endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index 57f79f1faa..159f05d1a5 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -97,6 +97,9 @@ public: } void maybeQuitOnLastWindowClosed(); +#ifndef QT_NO_CURSOR + void applyCursor(); +#endif QPoint globalPosition() const { Q_Q(const QWindow); diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index f99edc6194..2eab7b25c5 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -414,7 +414,7 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal if (clipLine(rx1, ry1, rx2, ry2)) return; - const int half = 31; + const int half = legacyRounding ? 31 : 0; int x1 = toF26Dot6(rx1) + half; int y1 = toF26Dot6(ry1) + half; int x2 = toF26Dot6(rx2) + half; @@ -707,7 +707,7 @@ static void drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, if (stroker->clipLine(rx1, ry1, rx2, ry2)) return; - static const int half = 31; + const int half = stroker->legacyRounding ? 31 : 0; int x1 = toF26Dot6(rx1) + half; int y1 = toF26Dot6(ry1) + half; int x2 = toF26Dot6(rx2) + half; diff --git a/src/gui/painting/qcosmeticstroker_p.h b/src/gui/painting/qcosmeticstroker_p.h index f71b87d79d..467eb7a836 100644 --- a/src/gui/painting/qcosmeticstroker_p.h +++ b/src/gui/painting/qcosmeticstroker_p.h @@ -93,11 +93,16 @@ public: patternSize(0), patternLength(0), patternOffset(0), + legacyRounding(false), current_span(0), lastDir(LeftToRight), lastAxisAligned(false) { setup(); } + ~QCosmeticStroker() { free(pattern); free(reversePattern); } + + void setLegacyRoundingEnabled(bool legacyRoundingEnabled) { legacyRounding = legacyRoundingEnabled; } + void drawLine(const QPointF &p1, const QPointF &p2); void drawPath(const QVectorPath &path); void drawPoints(const QPoint *points, int num); @@ -119,6 +124,8 @@ public: int patternLength; int patternOffset; + bool legacyRounding; + enum { NSPANS = 255 }; QT_FT_Span spans[NSPANS]; int current_span; diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index a2bac58d6c..1e5a00e835 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -1467,6 +1467,8 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd) painter->setRenderHint(QPainter::SmoothPixmapTransform, nh & QPainter::SmoothPixmapTransform); if (xored & QPainter::NonCosmeticDefaultPen) painter->setRenderHint(QPainter::NonCosmeticDefaultPen, nh & QPainter::NonCosmeticDefaultPen); + if (xored & QPainter::Qt4CompatiblePainting) + painter->setRenderHint(QPainter::Qt4CompatiblePainting, nh & QPainter::Qt4CompatiblePainting); break; } case QPaintBufferPrivate::Cmd_SetOpacity: { diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 5228fdcf1d..e0eab8dc73 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -644,6 +644,7 @@ QRasterPaintEngineState::QRasterPaintEngineState() flags.fast_pen = true; flags.antialiased = false; flags.bilinear = false; + flags.legacy_rounding = false; flags.fast_text = true; flags.int_xform = true; flags.tx_noshear = true; @@ -927,6 +928,7 @@ void QRasterPaintEngine::renderHintsChanged() s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing); s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform); + s->flags.legacy_rounding = !bool(s->renderHints & QPainter::Antialiasing) && bool(s->renderHints & QPainter::Qt4CompatiblePainting); if (was_aa != s->flags.antialiased) s->strokeFlags |= DirtyHints; @@ -1524,6 +1526,7 @@ void QRasterPaintEngine::drawRects(const QRect *rects, int rectCount) QRectVectorPath path; if (s->flags.fast_pen) { QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i = 0; i < rectCount; ++i) { path.set(rects[i]); stroker.drawPath(path); @@ -1570,6 +1573,7 @@ void QRasterPaintEngine::drawRects(const QRectF *rects, int rectCount) QRectVectorPath path; if (s->flags.fast_pen) { QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i = 0; i < rectCount; ++i) { path.set(rects[i]); stroker.drawPath(path); @@ -1603,6 +1607,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) if (s->flags.fast_pen) { QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPath(path); } else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) { qreal width = s->lastPen.isCosmetic() @@ -1658,12 +1663,16 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) QPaintEngineEx::stroke(path, pen); } -static inline QRect toNormalizedFillRect(const QRectF &rect) +QRect QRasterPaintEngine::toNormalizedFillRect(const QRectF &rect) { - int x1 = qRound(rect.x() + aliasedCoordinateDelta); - int y1 = qRound(rect.y() + aliasedCoordinateDelta); - int x2 = qRound(rect.right() + aliasedCoordinateDelta); - int y2 = qRound(rect.bottom() + aliasedCoordinateDelta); + QRasterPaintEngineState *s = state(); + + qreal delta = s->flags.legacy_rounding ? aliasedCoordinateDelta : qreal(0); + + int x1 = qRound(rect.x() + delta); + int y1 = qRound(rect.y() + delta); + int x2 = qRound(rect.right() + delta); + int y2 = qRound(rect.bottom() + delta); if (x2 < x1) qSwap(x1, x2); @@ -1941,6 +1950,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly QVectorPath vp((qreal *) points, pointCount, 0, QVectorPath::polygonFlags(mode)); if (s->flags.fast_pen) { QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPath(vp); } else { QPaintEngineEx::stroke(vp, s->lastPen); @@ -2005,6 +2015,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg if (s->flags.fast_pen) { QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPath(vp); } else { QPaintEngineEx::stroke(vp, s->lastPen); @@ -2233,7 +2244,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe // as fillRect will apply the aliased coordinate delta we need to // subtract it here as we don't use it for image drawing QTransform old = s->matrix; - s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); + + if (s->flags.legacy_rounding) + s->matrix = s->matrix * QTransform::fromTranslate(-aliasedCoordinateDelta, -aliasedCoordinateDelta); // Do whatever fillRect() does, but without premultiplying the color if it's already premultiplied. QRgb color = img.pixel(sr_l, sr_t); @@ -2376,8 +2389,9 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) { d->initializeRasterizer(&d->image_filler_xform); d->rasterizer->setAntialiased(s->flags.antialiased); + d->rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); - const QPointF offs = s->flags.antialiased ? QPointF() : QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta); + const QPointF offs = s->flags.legacy_rounding ? QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta) : QPointF(); const QRectF &rect = r.normalized(); const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f) - offs; @@ -2390,7 +2404,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe return; } #endif - const qreal offs = s->flags.antialiased ? qreal(0) : aliasedCoordinateDelta; + const qreal offs = s->flags.legacy_rounding ? aliasedCoordinateDelta : qreal(0); QPainterPath path; path.addRect(r); QTransform m = s->matrix; @@ -2471,6 +2485,7 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, if (s->flags.tx_noshear || s->matrix.type() == QTransform::TxScale) { d->initializeRasterizer(&d->image_filler_xform); d->rasterizer->setAntialiased(s->flags.antialiased); + d->rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); const QRectF &rect = r.normalized(); const QPointF a = s->matrix.map((rect.topLeft() + rect.bottomLeft()) * 0.5f); @@ -2802,7 +2817,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, rightShift = 3; // divide by 8 int margin = fontEngine->glyphMargin(glyphType); - const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); + const QFixed offs = s->flags.legacy_rounding ? QFixed::fromReal(aliasedCoordinateDelta) : QFixed(); const uchar *bits = image.bits(); for (int i=0; i<numGlyphs; ++i) { @@ -3078,6 +3093,7 @@ void QRasterPaintEngine::drawPoints(const QPointF *points, int pointCount) } QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPoints(points, pointCount); } @@ -3097,6 +3113,7 @@ void QRasterPaintEngine::drawPoints(const QPoint *points, int pointCount) } QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); stroker.drawPoints(points, pointCount); } @@ -3117,6 +3134,7 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) if (s->flags.fast_pen) { QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i=0; i<lineCount; ++i) { const QLine &l = lines[i]; stroker.drawLine(l.p1(), l.p2()); @@ -3188,6 +3206,7 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) return; if (s->flags.fast_pen) { QCosmeticStroker stroker(s, d->deviceRect); + stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding); for (int i=0; i<lineCount; ++i) { QLineF line = lines[i]; stroker.drawLine(line.p1(), line.p2()); @@ -3420,6 +3439,7 @@ void QRasterPaintEnginePrivate::initializeRasterizer(QSpanData *data) QRasterPaintEngineState *s = q->state(); rasterizer->setAntialiased(s->flags.antialiased); + rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); QRect clipRect(deviceRect); ProcessSpans blend; @@ -3484,6 +3504,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline, if (!s->flags.antialiased) { rasterizer->setAntialiased(s->flags.antialiased); + rasterizer->setLegacyRoundingEnabled(s->flags.legacy_rounding); rasterizer->setClipRect(deviceRect); rasterizer->initialize(callback, userData); diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index e1beff047e..8fb72edabd 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -110,6 +110,7 @@ public: uint non_complex_pen : 1; // can use rasterizer, rather than stroker uint antialiased : 1; uint bilinear : 1; + uint legacy_rounding : 1; uint fast_text : 1; uint int_xform : 1; uint tx_noshear : 1; @@ -246,6 +247,8 @@ private: bool setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op); + QRect toNormalizedFillRect(const QRectF &rect); + inline void ensureBrush(const QBrush &brush) { if (!qbrush_fast_equals(state()->lastBrush, brush) || (brush.style() != Qt::NoBrush && state()->fillFlags)) updateBrush(brush); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 02555b6fb6..69267b259b 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1421,6 +1421,11 @@ void QPainterPrivate::updateState(QPainterState *newState) of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic pen with a width of 1. + \value Qt4CompatiblePainting Compatibility hint telling the engine to use the + same X11 based fill rules as in Qt 4, where aliased rendering is offset + by slightly less than half a pixel. Potentially useful when porting a + Qt 4 application to Qt 5. + \sa renderHints(), setRenderHint(), {QPainter#Rendering Quality}{Rendering Quality}, {Concentric Circles Example} diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index c6c0e39ba0..a393b291e3 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -94,7 +94,8 @@ public: TextAntialiasing = 0x02, SmoothPixmapTransform = 0x04, HighQualityAntialiasing = 0x08, - NonCosmeticDefaultPen = 0x10 + NonCosmeticDefaultPen = 0x10, + Qt4CompatiblePainting = 0x20 }; Q_DECLARE_FLAGS(RenderHints, RenderHint) diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index fca037b964..e418f2c326 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -129,7 +129,7 @@ public: ~QScanConverter(); void begin(int top, int bottom, int left, int right, - Qt::FillRule fillRule, QSpanBuffer *spanBuffer); + Qt::FillRule fillRule, bool legacyRounding, QSpanBuffer *spanBuffer); void end(); void mergeCurve(const QT_FT_Vector &a, const QT_FT_Vector &b, @@ -177,6 +177,7 @@ private: Q16Dot16 m_rightFP; int m_fillRuleMask; + bool m_legacyRounding; int m_x; int m_y; @@ -196,6 +197,7 @@ class QRasterizerPrivate { public: bool antialiased; + bool legacyRounding; ProcessSpans blend; void *data; QRect clipRect; @@ -219,7 +221,8 @@ QScanConverter::~QScanConverter() } void QScanConverter::begin(int top, int bottom, int left, int right, - Qt::FillRule fillRule, QSpanBuffer *spanBuffer) + Qt::FillRule fillRule, bool legacyRounding, + QSpanBuffer *spanBuffer) { m_top = top; m_bottom = bottom; @@ -229,6 +232,7 @@ void QScanConverter::begin(int top, int bottom, int left, int right, m_lines.reset(); m_fillRuleMask = fillRule == Qt::WindingFill ? ~0x0 : 0x1; + m_legacyRounding = legacyRounding; m_spanBuffer = spanBuffer; } @@ -595,16 +599,20 @@ void QScanConverter::mergeLine(QT_FT_Vector a, QT_FT_Vector b) winding = -1; } - a.x += COORD_OFFSET; - a.y += COORD_OFFSET; - b.x += COORD_OFFSET; - b.y += COORD_OFFSET; + if (m_legacyRounding) { + a.x += COORD_OFFSET; + a.y += COORD_OFFSET; + b.x += COORD_OFFSET; + b.y += COORD_OFFSET; + } + + int rounding = m_legacyRounding ? COORD_ROUNDING : 0; - int iTop = qMax(m_top, int((a.y + 32 - COORD_ROUNDING) >> 6)); - int iBottom = qMin(m_bottom, int((b.y - 32 - COORD_ROUNDING) >> 6)); + int iTop = qMax(m_top, int((a.y + 32 - rounding) >> 6)); + int iBottom = qMin(m_bottom, int((b.y - 32 - rounding) >> 6)); if (iTop <= iBottom) { - Q16Dot16 aFP = Q16Dot16Factor/2 + (a.x << 10) - COORD_ROUNDING; + Q16Dot16 aFP = Q16Dot16Factor/2 + (a.x << 10) - rounding; if (b.x == a.x) { Line line = { qBound(m_leftFP, aFP, m_rightFP), 0, iTop, iBottom, winding }; @@ -635,6 +643,7 @@ void QScanConverter::mergeLine(QT_FT_Vector a, QT_FT_Vector b) QRasterizer::QRasterizer() : d(new QRasterizerPrivate) { + d->legacyRounding = false; } QRasterizer::~QRasterizer() @@ -658,6 +667,11 @@ void QRasterizer::setClipRect(const QRect &clipRect) d->clipRect = clipRect; } +void QRasterizer::setLegacyRoundingEnabled(bool legacyRoundingEnabled) +{ + d->legacyRounding = legacyRoundingEnabled; +} + static Q16Dot16 intersectPixelFP(int x, Q16Dot16 top, Q16Dot16 bottom, Q16Dot16 leftIntersectX, Q16Dot16 rightIntersectX, Q16Dot16 slope, Q16Dot16 invSlope) { Q16Dot16 leftX = IntToQ16Dot16(x); @@ -775,7 +789,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, pb = npb; } - if (!d->antialiased) { + if (!d->antialiased && d->legacyRounding) { pa.rx() += (COORD_OFFSET - COORD_ROUNDING)/64.; pa.ry() += (COORD_OFFSET - COORD_ROUNDING)/64.; pb.rx() += (COORD_OFFSET - COORD_ROUNDING)/64.; @@ -1174,13 +1188,15 @@ void QRasterizer::rasterize(const QT_FT_Outline *outline, Qt::FillRule fillRule) max_y = qMax(p.y, max_y); } - int iTopBound = qMax(d->clipRect.top(), int((min_y + 32 + COORD_OFFSET - COORD_ROUNDING) >> 6)); - int iBottomBound = qMin(d->clipRect.bottom(), int((max_y - 32 + COORD_OFFSET - COORD_ROUNDING) >> 6)); + int rounding = d->legacyRounding ? COORD_OFFSET - COORD_ROUNDING : 0; + + int iTopBound = qMax(d->clipRect.top(), int((min_y + 32 + rounding) >> 6)); + int iBottomBound = qMin(d->clipRect.bottom(), int((max_y - 32 + rounding) >> 6)); if (iTopBound > iBottomBound) return; - d->scanConverter.begin(iTopBound, iBottomBound, d->clipRect.left(), d->clipRect.right(), fillRule, &buffer); + d->scanConverter.begin(iTopBound, iBottomBound, d->clipRect.left(), d->clipRect.right(), fillRule, d->legacyRounding, &buffer); int first = 0; for (int i = 0; i < outline->n_contours; ++i) { @@ -1210,13 +1226,15 @@ void QRasterizer::rasterize(const QPainterPath &path, Qt::FillRule fillRule) QRectF bounds = path.controlPointRect(); - int iTopBound = qMax(d->clipRect.top(), int(bounds.top() + 0.5 + (COORD_OFFSET - COORD_ROUNDING)/64.)); - int iBottomBound = qMin(d->clipRect.bottom(), int(bounds.bottom() - 0.5 + (COORD_OFFSET - COORD_ROUNDING)/64.)); + double rounding = d->legacyRounding ? (COORD_OFFSET - COORD_ROUNDING) / 64. : 0.0; + + int iTopBound = qMax(d->clipRect.top(), int(bounds.top() + 0.5 + rounding)); + int iBottomBound = qMin(d->clipRect.bottom(), int(bounds.bottom() - 0.5 + rounding)); if (iTopBound > iBottomBound) return; - d->scanConverter.begin(iTopBound, iBottomBound, d->clipRect.left(), d->clipRect.right(), fillRule, &buffer); + d->scanConverter.begin(iTopBound, iBottomBound, d->clipRect.left(), d->clipRect.right(), fillRule, d->legacyRounding, &buffer); int subpathStart = 0; QT_FT_Vector last = { 0, 0 }; diff --git a/src/gui/painting/qrasterizer_p.h b/src/gui/painting/qrasterizer_p.h index 48e9982532..f535db8e6a 100644 --- a/src/gui/painting/qrasterizer_p.h +++ b/src/gui/painting/qrasterizer_p.h @@ -74,6 +74,7 @@ public: void setAntialiased(bool antialiased); void setClipRect(const QRect &clipRect); + void setLegacyRoundingEnabled(bool legacyRoundingEnabled); void initialize(ProcessSpans blend, void *data); diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index 33c6ddd1cd..8f6025fdf0 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -666,13 +666,13 @@ void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("s%1").arg(formatIndex)); writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("section")); writer.writeEmptyElement(styleNS, QString::fromLatin1("section-properties")); - if (format.hasProperty(QTextFormat::BlockTopMargin)) + if (format.hasProperty(QTextFormat::FrameTopMargin)) writer.writeAttribute(foNS, QString::fromLatin1("margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) ); - if (format.hasProperty(QTextFormat::BlockBottomMargin)) + if (format.hasProperty(QTextFormat::FrameBottomMargin)) writer.writeAttribute(foNS, QString::fromLatin1("margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) ); - if (format.hasProperty(QTextFormat::BlockLeftMargin)) + if (format.hasProperty(QTextFormat::FrameLeftMargin)) writer.writeAttribute(foNS, QString::fromLatin1("margin-left"), pixelToPoint(qMax(qreal(0.), format.leftMargin())) ); - if (format.hasProperty(QTextFormat::BlockRightMargin)) + if (format.hasProperty(QTextFormat::FrameRightMargin)) writer.writeAttribute(foNS, QString::fromLatin1("margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) ); writer.writeEndElement(); // style diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 4a2b2b11d1..6ef4eda5fc 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -86,7 +86,7 @@ public: depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1; numSamples = -1; swapInterval = -1; - majorVersion = 1; + majorVersion = 2; minorVersion = 0; profile = QGLFormat::NoProfile; } diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 0cc69d129c..8306a47e4f 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -149,6 +149,7 @@ QCoreTextFontDatabase::QCoreTextFontDatabase() // layout of the primary display NSDictionary *d = (NSDictionary *) IODisplayCreateInfoDictionary(iodisplay, kIODisplayOnlyPreferredName); uint displaySubpixelLayout = [[d objectForKey:@kDisplaySubPixelLayout] unsignedIntValue]; + [d release]; font_smoothing = (displaySubpixelLayout == kDisplaySubPixelLayoutUndefined ? 0 : 1); [pool release]; @@ -382,6 +383,7 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData NSLog(@"Unable to register font: %@", error); CFRelease(error); } + CGFontRelease(cgFont); } } else { CFErrorRef error; diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index c453cb7d1b..d989de0abb 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -501,6 +501,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition } CGContextRelease(ctx); + CGColorSpaceRelease(colorspace); return im; } diff --git a/src/platformsupport/linuxaccessibility/application.cpp b/src/platformsupport/linuxaccessibility/application.cpp index 0b9f1ce2e5..c2049e536a 100644 --- a/src/platformsupport/linuxaccessibility/application.cpp +++ b/src/platformsupport/linuxaccessibility/application.cpp @@ -42,7 +42,7 @@ #include "application_p.h" -#include <QtWidgets/qapplication.h> +#include <QtCore/qcoreapplication.h> #include <QtDBus/qdbuspendingreply.h> #include <qdebug.h> @@ -204,7 +204,7 @@ void QSpiApplicationAdaptor::notifyKeyboardListenerCallback(const QDBusMessage& delete event.second; } else { QPair<QObject*, QKeyEvent*> event = keyEvents.dequeue(); - QApplication::postEvent(event.first, event.second); + QCoreApplication::postEvent(event.first, event.second); } } @@ -213,7 +213,7 @@ void QSpiApplicationAdaptor::notifyKeyboardListenerError(const QDBusError& error qWarning() << QStringLiteral("QSpiApplication::keyEventError ") << error.name() << error.message(); while (!keyEvents.isEmpty()) { QPair<QObject*, QKeyEvent*> event = keyEvents.dequeue(); - QApplication::postEvent(event.first, event.second); + QCoreApplication::postEvent(event.first, event.second); } } diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index 33c0750263..f69e2365d8 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -42,10 +42,9 @@ #include "atspiadaptor_p.h" #include <QtGui/qwindow.h> -#include <QtWidgets/qapplication.h> +#include <QtGui/qguiapplication.h> #include <qdbusmessage.h> #include <qdbusreply.h> -#include <QtWidgets/qwidget.h> #include <qclipboard.h> #include <qdebug.h> @@ -1405,7 +1404,7 @@ bool AtSpiAdaptor::accessibleInterface(const QAIPointer &interface, const QStrin } connection.send(message.createReply(QVariant::fromValue(children))); } else { - qAtspiDebug() << "WARNING: AtSpiAdaptor::handleMessage does not implement " << function << message.path(); + qAtspiDebug() << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path(); return false; } return true; @@ -1519,8 +1518,9 @@ QString AtSpiAdaptor::pathForInterface(const QAIPointer &interface, bool inDestr QAIPointer interfaceWithObject = interface; QString path; - if (interface->role() == QAccessible::MenuItem && interface->object() && - inheritsQAction(interface->object())) { + QAccessible::Role role = interface->role(); + if (((role == QAccessible::MenuItem) || (role == QAccessible::Separator)) && + interface->object() && inheritsQAction(interface->object())) { interfaceWithObject = QAIPointer(interface->parent()); int childIndex = interfaceWithObject->indexOfChild(interface.data()); path.append(QString::fromLatin1("/%1").arg(childIndex)); @@ -1541,7 +1541,7 @@ QString AtSpiAdaptor::pathForInterface(const QAIPointer &interface, bool inDestr quintptr uintptr = reinterpret_cast<quintptr>(interfaceWithObject->object()); path.prepend(QLatin1String(QSPI_OBJECT_PATH_PREFIX) + QString::number(uintptr)); - if (!inDestructor && !m_handledObjects.contains(uintptr)) + if (!inDestructor && (!m_handledObjects.contains(uintptr) || m_handledObjects.value(uintptr) == 0)) m_handledObjects[uintptr] = QPointer<QObject>(interfaceWithObject->object()); return path; @@ -1673,7 +1673,7 @@ bool AtSpiAdaptor::componentInterface(const QAIPointer &interface, const QString qAtspiDebug() << "SetSize is not implemented."; sendReply(connection, message, false); } else { - qAtspiDebug() << "WARNING: AtSpiAdaptor::handleMessage does not implement " << function << message.path(); + qAtspiDebug() << "WARNING: AtSpiAdaptor::componentInterface does not implement " << function << message.path(); return false; } return true; @@ -1727,7 +1727,7 @@ bool AtSpiAdaptor::actionInterface(const QAIPointer &interface, const QString &f else sendReply(connection, message, QString()); } else { - qAtspiDebug() << "WARNING: AtSpiAdaptor::handleMessage does not implement " << function << message.path(); + qAtspiDebug() << "WARNING: AtSpiAdaptor::actionInterface does not implement " << function << message.path(); return false; } return true; @@ -1884,7 +1884,7 @@ bool AtSpiAdaptor::textInterface(const QAIPointer &interface, const QString &fun interface->textInterface()->setSelection(selectionNum, startOffset, endOffset); sendReply(connection, message, true); } else { - qAtspiDebug() << "WARNING: AtSpiAdaptor::handleMessage does not implement " << function << message.path(); + qAtspiDebug() << "WARNING: AtSpiAdaptor::textInterface does not implement " << function << message.path(); return false; } return true; @@ -2080,7 +2080,7 @@ bool AtSpiAdaptor::editableTextInterface(const QAIPointer &interface, const QStr } else if (function == QLatin1String("")) { connection.send(message.createReply()); } else { - qAtspiDebug() << "WARNING: AtSpiAdaptor::handleMessage does not implement " << function << message.path(); + qAtspiDebug() << "WARNING: AtSpiAdaptor::editableTextInterface does not implement " << function << message.path(); return false; } return true; @@ -2125,7 +2125,7 @@ bool AtSpiAdaptor::valueInterface(const QAIPointer &interface, const QString &fu connection.send(message.createReply( QVariant::fromValue(QDBusVariant(QVariant::fromValue(val))))); } else { - qAtspiDebug() << "WARNING: AtSpiAdaptor::handleMessage does not implement " << function << message.path(); + qAtspiDebug() << "WARNING: AtSpiAdaptor::valueInterface does not implement " << function << message.path(); return false; } return true; @@ -2335,7 +2335,7 @@ bool AtSpiAdaptor::tableInterface(const QAIPointer &interface, const QString &fu int row = message.arguments().at(0).toInt(); connection.send(message.createReply(interface->tableInterface()->unselectRow(row))); } else { - qAtspiDebug() << "WARNING: AtSpiAdaptor::handleMessage does not implement " << function << message.path(); + qAtspiDebug() << "WARNING: AtSpiAdaptor::tableInterface does not implement " << function << message.path(); return false; } return true; diff --git a/src/platformsupport/linuxaccessibility/bridge.cpp b/src/platformsupport/linuxaccessibility/bridge.cpp index 6248056fb2..f22dc4e191 100644 --- a/src/platformsupport/linuxaccessibility/bridge.cpp +++ b/src/platformsupport/linuxaccessibility/bridge.cpp @@ -107,80 +107,79 @@ struct RoleMapping { QAccessible::Role role; AtspiRole spiRole; const char *name; - const char *localizedName; }; static RoleMapping map[] = { - { QAccessible::NoRole, ATSPI_ROLE_INVALID, "invalid", QT_TR_NOOP("invalid role") }, - { QAccessible::TitleBar, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("title bar") }, - { QAccessible::MenuBar, ATSPI_ROLE_MENU_BAR, "menu bar", QT_TR_NOOP("menu bar") }, - { QAccessible::ScrollBar, ATSPI_ROLE_SCROLL_BAR, "scroll bar", QT_TR_NOOP("scroll bar") }, - { QAccessible::Grip, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("grip") }, - { QAccessible::Sound, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("sound") }, - { QAccessible::Cursor, ATSPI_ROLE_ARROW, "arrow", QT_TR_NOOP("cursor") }, - { QAccessible::Caret, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("caret") }, - { QAccessible::AlertMessage, ATSPI_ROLE_ALERT, "alert", QT_TR_NOOP("alert message") }, - { QAccessible::Window, ATSPI_ROLE_WINDOW, "window", QT_TR_NOOP("window") }, - { QAccessible::Client, ATSPI_ROLE_FILLER, "filler", QT_TR_NOOP("filler") }, - { QAccessible::PopupMenu, ATSPI_ROLE_POPUP_MENU, "popup menu", QT_TR_NOOP("popup menu") }, - { QAccessible::MenuItem, ATSPI_ROLE_MENU_ITEM, "menu item", QT_TR_NOOP("menu item") }, - { QAccessible::ToolTip, ATSPI_ROLE_TOOL_TIP, "tool tip", QT_TR_NOOP("tool tip") }, - { QAccessible::Application, ATSPI_ROLE_APPLICATION, "application", QT_TR_NOOP("application") }, - { QAccessible::Document, ATSPI_ROLE_DOCUMENT_FRAME, "document frame", QT_TR_NOOP("document") }, - { QAccessible::Pane, ATSPI_ROLE_PANEL, "panel", QT_TR_NOOP("pane") }, - { QAccessible::Chart, ATSPI_ROLE_CHART, "chart", QT_TR_NOOP("chart") }, - { QAccessible::Dialog, ATSPI_ROLE_DIALOG, "dialog", QT_TR_NOOP("dialog") }, - { QAccessible::Border, ATSPI_ROLE_FRAME, "frame", QT_TR_NOOP("border") }, - { QAccessible::Grouping, ATSPI_ROLE_PANEL, "panel", QT_TR_NOOP("grouping") }, - { QAccessible::Separator, ATSPI_ROLE_SEPARATOR, "separator", QT_TR_NOOP("separator") }, - { QAccessible::ToolBar, ATSPI_ROLE_TOOL_BAR, "tool bar", QT_TR_NOOP("tool bar") }, - { QAccessible::StatusBar, ATSPI_ROLE_STATUS_BAR, "statusbar", QT_TR_NOOP("status bar") }, - { QAccessible::Table, ATSPI_ROLE_TABLE, "table", QT_TR_NOOP("table") }, - { QAccessible::ColumnHeader, ATSPI_ROLE_TABLE_COLUMN_HEADER, "column header", QT_TR_NOOP("column header") }, - { QAccessible::RowHeader, ATSPI_ROLE_TABLE_ROW_HEADER, "row header", QT_TR_NOOP("row header") }, - { QAccessible::Column, ATSPI_ROLE_TABLE_CELL, "table cell", QT_TR_NOOP("column") }, - { QAccessible::Row, ATSPI_ROLE_TABLE_CELL, "table cell", QT_TR_NOOP("row") }, - { QAccessible::Cell, ATSPI_ROLE_TABLE_CELL, "table cell", QT_TR_NOOP("cell") }, - { QAccessible::Link, ATSPI_ROLE_LINK, "link", QT_TR_NOOP("link") }, - { QAccessible::HelpBalloon, ATSPI_ROLE_DIALOG, "dialog", QT_TR_NOOP("help balloon") }, - { QAccessible::Assistant, ATSPI_ROLE_DIALOG, "dialog", QT_TR_NOOP("assistant") }, - { QAccessible::List, ATSPI_ROLE_LIST, "list", QT_TR_NOOP("list") }, - { QAccessible::ListItem, ATSPI_ROLE_LIST_ITEM, "list item", QT_TR_NOOP("list item") }, - { QAccessible::Tree, ATSPI_ROLE_TREE, "tree", QT_TR_NOOP("tree") }, - { QAccessible::TreeItem, ATSPI_ROLE_TABLE_CELL, "tree item", QT_TR_NOOP("tree item") }, - { QAccessible::PageTab, ATSPI_ROLE_PAGE_TAB, "page tab", QT_TR_NOOP("page tab") }, - { QAccessible::PropertyPage, ATSPI_ROLE_PAGE_TAB, "page tab", QT_TR_NOOP("property page") }, - { QAccessible::Indicator, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("indicator") }, - { QAccessible::Graphic, ATSPI_ROLE_IMAGE, "image", QT_TR_NOOP("graphic") }, - { QAccessible::StaticText, ATSPI_ROLE_LABEL, "label", QT_TR_NOOP("label") }, - { QAccessible::EditableText, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("text") }, - { QAccessible::PushButton, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("push button") }, - { QAccessible::CheckBox, ATSPI_ROLE_CHECK_BOX, "check box", QT_TR_NOOP("check box") }, - { QAccessible::RadioButton, ATSPI_ROLE_RADIO_BUTTON, "radio button", QT_TR_NOOP("radio box") }, - { QAccessible::ComboBox, ATSPI_ROLE_COMBO_BOX, "combo box", QT_TR_NOOP("combo box") }, - { QAccessible::ProgressBar, ATSPI_ROLE_PROGRESS_BAR, "progress bar", QT_TR_NOOP("progress bar") }, - { QAccessible::Dial, ATSPI_ROLE_DIAL, "accelerator label", QT_TR_NOOP("dial") }, - { QAccessible::HotkeyField, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("hotkey field") }, //FIXME text? - { QAccessible::Slider, ATSPI_ROLE_SLIDER, "slider", QT_TR_NOOP("slider") }, - { QAccessible::SpinBox, ATSPI_ROLE_SPIN_BUTTON, "spin button", QT_TR_NOOP("spin box") }, - { QAccessible::Canvas, ATSPI_ROLE_CANVAS, "canvas", QT_TR_NOOP("canvas") }, - { QAccessible::Animation, ATSPI_ROLE_ANIMATION, "animation", QT_TR_NOOP("animation") }, - { QAccessible::Equation, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("equation") }, - { QAccessible::ButtonDropDown, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("button drop down") }, - { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("button menu") }, - { QAccessible::ButtonDropGrid, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("button drop grid") }, - { QAccessible::Whitespace, ATSPI_ROLE_FILLER, "filler", QT_TR_NOOP("whitespace") }, - { QAccessible::PageTabList, ATSPI_ROLE_PAGE_TAB_LIST, "page tab list", QT_TR_NOOP("page tab list") }, - { QAccessible::Clock, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("clock") }, - { QAccessible::Splitter, ATSPI_ROLE_SPLIT_PANE, "split pane", QT_TR_NOOP("splitter") }, - { QAccessible::LayeredPane, ATSPI_ROLE_LAYERED_PANE, "layered pane", QT_TR_NOOP("layered pane") }, - { QAccessible::UserRole, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("user role") } + { QAccessible::NoRole, ATSPI_ROLE_INVALID, QT_TR_NOOP("invalid role") }, + { QAccessible::TitleBar, ATSPI_ROLE_TEXT, QT_TR_NOOP("title bar") }, + { QAccessible::MenuBar, ATSPI_ROLE_MENU_BAR, QT_TR_NOOP("menu bar") }, + { QAccessible::ScrollBar, ATSPI_ROLE_SCROLL_BAR, QT_TR_NOOP("scroll bar") }, + { QAccessible::Grip, ATSPI_ROLE_UNKNOWN, QT_TR_NOOP("grip") }, + { QAccessible::Sound, ATSPI_ROLE_UNKNOWN, QT_TR_NOOP("sound") }, + { QAccessible::Cursor, ATSPI_ROLE_UNKNOWN, QT_TR_NOOP("cursor") }, + { QAccessible::Caret, ATSPI_ROLE_UNKNOWN, QT_TR_NOOP("cursor") }, + { QAccessible::AlertMessage, ATSPI_ROLE_ALERT, QT_TR_NOOP("alert message") }, + { QAccessible::Window, ATSPI_ROLE_WINDOW, QT_TR_NOOP("window") }, + { QAccessible::Client, ATSPI_ROLE_FILLER, QT_TR_NOOP("filler") }, + { QAccessible::PopupMenu, ATSPI_ROLE_POPUP_MENU, QT_TR_NOOP("popup menu") }, + { QAccessible::MenuItem, ATSPI_ROLE_MENU_ITEM, QT_TR_NOOP("menu item") }, + { QAccessible::ToolTip, ATSPI_ROLE_TOOL_TIP, QT_TR_NOOP("tool tip") }, + { QAccessible::Application, ATSPI_ROLE_APPLICATION, QT_TR_NOOP("application") }, + { QAccessible::Document, ATSPI_ROLE_DOCUMENT_FRAME, QT_TR_NOOP("document") }, + { QAccessible::Pane, ATSPI_ROLE_PANEL, QT_TR_NOOP("panel") }, + { QAccessible::Chart, ATSPI_ROLE_CHART, QT_TR_NOOP("chart") }, + { QAccessible::Dialog, ATSPI_ROLE_DIALOG, QT_TR_NOOP("dialog") }, + { QAccessible::Border, ATSPI_ROLE_FRAME, QT_TR_NOOP("frame") }, + { QAccessible::Grouping, ATSPI_ROLE_PANEL, QT_TR_NOOP("panel") }, + { QAccessible::Separator, ATSPI_ROLE_SEPARATOR, QT_TR_NOOP("separator") }, + { QAccessible::ToolBar, ATSPI_ROLE_TOOL_BAR, QT_TR_NOOP("tool bar") }, + { QAccessible::StatusBar, ATSPI_ROLE_STATUS_BAR, QT_TR_NOOP("status bar") }, + { QAccessible::Table, ATSPI_ROLE_TABLE, QT_TR_NOOP("table") }, + { QAccessible::ColumnHeader, ATSPI_ROLE_TABLE_COLUMN_HEADER, QT_TR_NOOP("column header") }, + { QAccessible::RowHeader, ATSPI_ROLE_TABLE_ROW_HEADER, QT_TR_NOOP("row header") }, + { QAccessible::Column, ATSPI_ROLE_TABLE_CELL, QT_TR_NOOP("column") }, + { QAccessible::Row, ATSPI_ROLE_TABLE_ROW, QT_TR_NOOP("row") }, + { QAccessible::Cell, ATSPI_ROLE_TABLE_CELL, QT_TR_NOOP("cell") }, + { QAccessible::Link, ATSPI_ROLE_LINK, QT_TR_NOOP("link") }, + { QAccessible::HelpBalloon, ATSPI_ROLE_DIALOG, QT_TR_NOOP("help balloon") }, + { QAccessible::Assistant, ATSPI_ROLE_DIALOG, QT_TR_NOOP("assistant") }, + { QAccessible::List, ATSPI_ROLE_LIST, QT_TR_NOOP("list") }, + { QAccessible::ListItem, ATSPI_ROLE_LIST_ITEM, QT_TR_NOOP("list item") }, + { QAccessible::Tree, ATSPI_ROLE_TREE, QT_TR_NOOP("tree") }, + { QAccessible::TreeItem, ATSPI_ROLE_TABLE_CELL, QT_TR_NOOP("tree item") }, + { QAccessible::PageTab, ATSPI_ROLE_PAGE_TAB, QT_TR_NOOP("page tab") }, + { QAccessible::PropertyPage, ATSPI_ROLE_PAGE_TAB, QT_TR_NOOP("property page") }, + { QAccessible::Indicator, ATSPI_ROLE_UNKNOWN, QT_TR_NOOP("indicator") }, + { QAccessible::Graphic, ATSPI_ROLE_IMAGE, QT_TR_NOOP("graphic") }, + { QAccessible::StaticText, ATSPI_ROLE_LABEL, QT_TR_NOOP("label") }, + { QAccessible::EditableText, ATSPI_ROLE_TEXT, QT_TR_NOOP("text") }, + { QAccessible::PushButton, ATSPI_ROLE_PUSH_BUTTON, QT_TR_NOOP("push button") }, + { QAccessible::CheckBox, ATSPI_ROLE_CHECK_BOX, QT_TR_NOOP("check box") }, + { QAccessible::RadioButton, ATSPI_ROLE_RADIO_BUTTON, QT_TR_NOOP("radio button") }, + { QAccessible::ComboBox, ATSPI_ROLE_COMBO_BOX, QT_TR_NOOP("combo box") }, + { QAccessible::ProgressBar, ATSPI_ROLE_PROGRESS_BAR, QT_TR_NOOP("progress bar") }, + { QAccessible::Dial, ATSPI_ROLE_DIAL, QT_TR_NOOP("dial") }, + { QAccessible::HotkeyField, ATSPI_ROLE_TEXT, QT_TR_NOOP("hotkey field") }, + { QAccessible::Slider, ATSPI_ROLE_SLIDER, QT_TR_NOOP("slider") }, + { QAccessible::SpinBox, ATSPI_ROLE_SPIN_BUTTON, QT_TR_NOOP("spin box") }, + { QAccessible::Canvas, ATSPI_ROLE_CANVAS, QT_TR_NOOP("canvas") }, + { QAccessible::Animation, ATSPI_ROLE_ANIMATION, QT_TR_NOOP("animation") }, + { QAccessible::Equation, ATSPI_ROLE_TEXT, QT_TR_NOOP("equation") }, + { QAccessible::ButtonDropDown, ATSPI_ROLE_PUSH_BUTTON, QT_TR_NOOP("button drop down") }, + { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON, QT_TR_NOOP("button menu") }, + { QAccessible::ButtonDropGrid, ATSPI_ROLE_PUSH_BUTTON, QT_TR_NOOP("button drop grid") }, + { QAccessible::Whitespace, ATSPI_ROLE_FILLER, QT_TR_NOOP("whitespace") }, + { QAccessible::PageTabList, ATSPI_ROLE_PAGE_TAB_LIST, QT_TR_NOOP("page tab list") }, + { QAccessible::Clock, ATSPI_ROLE_UNKNOWN, QT_TR_NOOP("clock") }, + { QAccessible::Splitter, ATSPI_ROLE_SPLIT_PANE, QT_TR_NOOP("splitter") }, + { QAccessible::LayeredPane, ATSPI_ROLE_LAYERED_PANE, QT_TR_NOOP("layered pane") }, + { QAccessible::UserRole, ATSPI_ROLE_UNKNOWN, QT_TR_NOOP("unknown") } }; void QSpiAccessibleBridge::initializeConstantMappings() { for (uint i = 0; i < sizeof(map) / sizeof(RoleMapping); ++i) - qSpiRoleMapping.insert(map[i].role, RoleNames(map[i].spiRole, QLatin1String(map[i].name), tr(map[i].localizedName))); + qSpiRoleMapping.insert(map[i].role, RoleNames(map[i].spiRole, QLatin1String(map[i].name), tr(map[i].name))); } QT_END_NAMESPACE diff --git a/src/plugins/accessible/widgets/itemviews.cpp b/src/plugins/accessible/widgets/itemviews.cpp index 649863ed84..0aeff6e1a3 100644 --- a/src/plugins/accessible/widgets/itemviews.cpp +++ b/src/plugins/accessible/widgets/itemviews.cpp @@ -75,7 +75,7 @@ QAbstractItemView *QAccessibleTable::view() const int QAccessibleTable::logicalIndex(const QModelIndex &index) const { - if (!index.isValid()) + if (!view()->model() || !index.isValid()) return -1; int vHeader = verticalHeader() ? 1 : 0; int hHeader = horizontalHeader() ? 1 : 0; @@ -85,7 +85,7 @@ int QAccessibleTable::logicalIndex(const QModelIndex &index) const QAccessibleInterface *QAccessibleTable::childFromLogical(int logicalIndex) const { - if (!isValid()) + if (!view()->model()) return 0; logicalIndex--; // one based counting ftw @@ -179,6 +179,8 @@ QAccessibleTableCell *QAccessibleTable::cell(const QModelIndex &index) const QAccessibleInterface *QAccessibleTable::cellAt(int row, int column) const { + if (!view()->model()) + return 0; Q_ASSERT(role() != QAccessible::Tree); QModelIndex index = view()->model()->index(row, column, view()->rootIndex()); if (!index.isValid()) { @@ -195,42 +197,58 @@ QAccessibleInterface *QAccessibleTable::caption() const QString QAccessibleTable::columnDescription(int column) const { + if (!view()->model()) + return QString(); return view()->model()->headerData(column, Qt::Horizontal).toString(); } int QAccessibleTable::columnCount() const { + if (!view()->model()) + return 0; return view()->model()->columnCount(); } int QAccessibleTable::rowCount() const { + if (!view()->model()) + return 0; return view()->model()->rowCount(); } int QAccessibleTable::selectedCellCount() const { + if (!view()->selectionModel()) + return 0; return view()->selectionModel()->selectedIndexes().count(); } int QAccessibleTable::selectedColumnCount() const { + if (!view()->selectionModel()) + return 0; return view()->selectionModel()->selectedColumns().count(); } int QAccessibleTable::selectedRowCount() const { + if (!view()->selectionModel()) + return 0; return view()->selectionModel()->selectedRows().count(); } QString QAccessibleTable::rowDescription(int row) const { + if (!view()->model()) + return QString(); return view()->model()->headerData(row, Qt::Vertical).toString(); } QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const { QList<QAccessibleInterface*> cells; + if (!view()->selectionModel()) + return cells; Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedIndexes()) { cells.append(cell(index)); } @@ -239,6 +257,8 @@ QList<QAccessibleInterface *> QAccessibleTable::selectedCells() const QList<int> QAccessibleTable::selectedColumns() const { + if (!view()->selectionModel()) + return QList<int>(); QList<int> columns; Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedColumns()) { columns.append(index.column()); @@ -248,6 +268,8 @@ QList<int> QAccessibleTable::selectedColumns() const QList<int> QAccessibleTable::selectedRows() const { + if (!view()->selectionModel()) + return QList<int>(); QList<int> rows; Q_FOREACH (const QModelIndex &index, view()->selectionModel()->selectedRows()) { rows.append(index.row()); @@ -262,16 +284,22 @@ QAccessibleInterface *QAccessibleTable::summary() const bool QAccessibleTable::isColumnSelected(int column) const { + if (!view()->selectionModel()) + return false; return view()->selectionModel()->isColumnSelected(column, QModelIndex()); } bool QAccessibleTable::isRowSelected(int row) const { + if (!view()->selectionModel()) + return false; return view()->selectionModel()->isRowSelected(row, QModelIndex()); } bool QAccessibleTable::selectRow(int row) { + if (!view()->model() || !view()->selectionModel()) + return false; QModelIndex index = view()->model()->index(row, 0, view()->rootIndex()); if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection) return false; @@ -281,6 +309,8 @@ bool QAccessibleTable::selectRow(int row) bool QAccessibleTable::selectColumn(int column) { + if (!view()->model() || !view()->selectionModel()) + return false; QModelIndex index = view()->model()->index(0, column, view()->rootIndex()); if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection) return false; @@ -290,6 +320,8 @@ bool QAccessibleTable::selectColumn(int column) bool QAccessibleTable::unselectRow(int row) { + if (!view()->model() || !view()->selectionModel()) + return false; QModelIndex index = view()->model()->index(row, 0, view()->rootIndex()); if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection) return false; @@ -299,6 +331,8 @@ bool QAccessibleTable::unselectRow(int row) bool QAccessibleTable::unselectColumn(int column) { + if (!view()->model() || !view()->selectionModel()) + return false; QModelIndex index = view()->model()->index(0, column, view()->rootIndex()); if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection) return false; @@ -340,6 +374,8 @@ int QAccessibleTable::childCount() const int QAccessibleTable::indexOfChild(const QAccessibleInterface *iface) const { + if (!view()->model()) + return -1; Q_ASSERT(iface->role() != QAccessible::TreeItem); // should be handled by tree class if (iface->role() == QAccessible::Cell || iface->role() == QAccessible::ListItem) { const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface); @@ -403,7 +439,7 @@ void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t) QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const { - if (!isValid()) + if (!isValid() || !view()->model()) return QModelIndex(); const QTreeView *treeView = qobject_cast<const QTreeView*>(view()); @@ -421,6 +457,8 @@ QModelIndex QAccessibleTree::indexFromLogical(int row, int column) const QAccessibleInterface *QAccessibleTree::childAt(int x, int y) const { + if (!view()->model()) + return 0; QPoint viewportOffset = view()->viewport()->mapTo(view(), QPoint(0,0)); QPoint indexPosition = view()->mapFromGlobal(QPoint(x, y) - viewportOffset); @@ -451,7 +489,8 @@ int QAccessibleTree::childCount() const QAccessibleInterface *QAccessibleTree::child(int index) const { - Q_ASSERT(index >= 0); + if ((index < 0) || (!view()->model())) + return 0; int hHeader = horizontalHeader() ? 1 : 0; if (hHeader) { @@ -480,6 +519,8 @@ int QAccessibleTree::rowCount() const int QAccessibleTree::indexOfChild(const QAccessibleInterface *iface) const { + if (!view()->model()) + return -1; if (iface->role() == QAccessible::TreeItem) { const QAccessibleTableCell* cell = static_cast<const QAccessibleTableCell*>(iface); const QTreeView *treeView = qobject_cast<const QTreeView*>(view()); @@ -520,12 +561,16 @@ QString QAccessibleTree::rowDescription(int) const bool QAccessibleTree::isRowSelected(int row) const { + if (!view()->selectionModel()) + return false; QModelIndex index = indexFromLogical(row); return view()->selectionModel()->isRowSelected(index.row(), index.parent()); } bool QAccessibleTree::selectRow(int row) { + if (!view()->selectionModel()) + return false; QModelIndex index = indexFromLogical(row); if (!index.isValid() || view()->selectionMode() & QAbstractItemView::NoSelection) return false; diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index d98c49a1ce..67881d8680 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -119,7 +119,11 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) m_drag = o; m_executed_drop_action = Qt::IgnoreAction; - NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(m_drag->pixmap())); + QPixmap pm = m_drag->pixmap(); + if (pm.isNull()) + pm = defaultPixmap(); + + NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm)); QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacPasteboardMime::MIME_DND); m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy")); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 050a2e69d1..45c35cccbf 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -73,9 +73,12 @@ NSImage *qt_mac_cgimage_to_nsimage(CGImageRef iamge); NSImage *qt_mac_create_nsimage(const QPixmap &pm); NSSize qt_mac_toNSSize(const QSize &qtSize); +NSRect qt_mac_toNSRect(const QRect &rect); +QRect qt_mac_toQRect(const NSRect &rect); QColor qt_mac_toQColor(const NSColor *color); + // Creates a mutable shape, it's the caller's responsibility to release. HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 8841a65844..bd89f26fca 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -135,7 +135,10 @@ NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image) NSImage *qt_mac_create_nsimage(const QPixmap &pm) { QImage image = pm.toImage(); - return qt_mac_cgimage_to_nsimage(qt_mac_image_to_cgimage(image)); + CGImageRef cgImage = qt_mac_image_to_cgimage(image); + NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage); + CGImageRelease(cgImage); + return nsImage; } HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion) @@ -159,6 +162,16 @@ NSSize qt_mac_toNSSize(const QSize &qtSize) return NSMakeSize(qtSize.width(), qtSize.height()); } +NSRect qt_mac_toNSRect(const QRect &rect) +{ + return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); +} + +QRect qt_mac_toQRect(const NSRect &rect) +{ + return QRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); +} + QColor qt_mac_toQColor(const NSColor *color) { QColor qtColor; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index e4baaab3d3..4d35b3202e 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -218,10 +218,9 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) NSMenuItem *oldItem = [m_nativeMenu itemWithTag:(NSInteger) cocoaItem]; if (cocoaItem->sync() != oldItem) { - // native item was changed for some reason - if (!wasMerged) { + // native item was changed for some reason + if (!wasMerged && oldItem) [m_nativeMenu removeItem:oldItem]; - } QCocoaMenuItem* beforeItem = itemOrNull(m_menuItems.indexOf(cocoaItem) + 1); insertNative(cocoaItem, beforeItem); diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index a747a82d09..0ff160957f 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -67,6 +67,8 @@ public: const QPalette *palette(Palette type = SystemPalette) const; const QFont *font(Font type = SystemFont) const; + QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const; + QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const; QVariant themeHint(ThemeHint hint) const; diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index ddb550dd5f..967d65faec 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -54,7 +54,9 @@ #include "qcocoamenu.h" #include "qcocoamenubar.h" +#include <QtCore/qfileinfo.h> #include <QtGui/private/qguiapplication_p.h> +#include <QtGui/qpainter.h> #include <qpa/qplatformintegration.h> #include <qpa/qplatformnativeinterface.h> @@ -135,6 +137,143 @@ const QFont *QCocoaTheme::font(Font type) const return m_fonts.value(type, 0); } +// Defined in qpaintengine_mac.mm +extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); + +//! \internal +QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) +{ + QPixmap ret(width, height); + ret.fill(QColor(0, 0, 0, 0)); + + CGRect rect = CGRectMake(0, 0, width, height); + + CGContextRef ctx = qt_mac_cg_context(&ret); + CGAffineTransform old_xform = CGContextGetCTM(ctx); + CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform)); + CGContextConcatCTM(ctx, CGAffineTransformIdentity); + + ::RGBColor b; + b.blue = b.green = b.red = 255*255; + PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon); + CGContextRelease(ctx); + return ret; +} + +QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const +{ + OSType iconType = 0; + switch (sp) { + case MessageBoxQuestion: + iconType = kQuestionMarkIcon; + break; + case MessageBoxInformation: + iconType = kAlertNoteIcon; + break; + case MessageBoxWarning: + iconType = kAlertCautionIcon; + break; + case MessageBoxCritical: + iconType = kAlertStopIcon; + break; + case DesktopIcon: + iconType = kDesktopIcon; + break; + case TrashIcon: + iconType = kTrashIcon; + break; + case ComputerIcon: + iconType = kComputerIcon; + break; + case DriveFDIcon: + iconType = kGenericFloppyIcon; + break; + case DriveHDIcon: + iconType = kGenericHardDiskIcon; + break; + case DriveCDIcon: + case DriveDVDIcon: + iconType = kGenericCDROMIcon; + break; + case DriveNetIcon: + iconType = kGenericNetworkIcon; + break; + case DirOpenIcon: + iconType = kOpenFolderIcon; + break; + case DirClosedIcon: + case DirLinkIcon: + iconType = kGenericFolderIcon; + break; + case FileLinkIcon: + case FileIcon: + iconType = kGenericDocumentIcon; + break; + default: + break; + } + if (iconType != 0) { + QPixmap pixmap; + IconRef icon; + IconRef overlayIcon = 0; + if (iconType != kGenericApplicationIcon) { + GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon); + } else { + FSRef fsRef; + ProcessSerialNumber psn = { 0, kCurrentProcess }; + GetProcessBundleLocation(&psn, &fsRef); + GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0); + if (sp == MessageBoxCritical) { + overlayIcon = icon; + GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon); + } + } + + if (icon) { + pixmap = qt_mac_convert_iconref(icon, size.width(), size.height()); + ReleaseIconRef(icon); + } + + if (overlayIcon) { + QSizeF littleSize = size / 2; + QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize.width(), littleSize.height()); + QPainter painter(&pixmap); + painter.drawPixmap(littleSize.width(), littleSize.height(), overlayPix); + ReleaseIconRef(overlayIcon); + } + + return pixmap; + } + + return QPlatformTheme::standardPixmap(sp, size); +} + +QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const +{ + FSRef macRef; + OSStatus status = FSPathMakeRef(reinterpret_cast<const UInt8*>(fileInfo.canonicalFilePath().toUtf8().constData()), + &macRef, 0); + if (status != noErr) + return QPixmap(); + FSCatalogInfo info; + HFSUniStr255 macName; + status = FSGetCatalogInfo(&macRef, kIconServicesCatalogInfoMask, &info, &macName, 0, 0); + if (status != noErr) + return QPixmap(); + IconRef iconRef; + SInt16 iconLabel; + status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode, + kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag, + &iconRef, &iconLabel); + if (status != noErr) + return QPixmap(); + + QPixmap pixmap = qt_mac_convert_iconref(iconRef, size.width(), size.height()); + ReleaseIconRef(iconRef); + + return pixmap; +} + QVariant QCocoaTheme::themeHint(ThemeHint hint) const { switch (hint) { @@ -146,6 +285,11 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const return QVariant(int(MacKeyboardScheme)); case TabAllWidgets: return QVariant(bool([[NSApplication sharedApplication] isFullKeyboardAccessEnabled])); + case IconPixmapSizes: { + QList<int> sizes; + sizes << 16 << 32 << 64 << 128; + return QVariant::fromValue(sizes); + } default: break; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 014db378e7..d5dbe58de9 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -99,9 +99,10 @@ public: void setCocoaGeometry(const QRect &rect); void setVisible(bool visible); void setWindowFlags(Qt::WindowFlags flags); - Qt::WindowState setWindowState(Qt::WindowState state); + void setWindowState(Qt::WindowState state); void setWindowTitle(const QString &title); void setWindowFilePath(const QString &filePath); + void setWindowIcon(const QIcon &icon); void raise(); void lower(); void propagateSizeHints(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index f4a4936c28..b9ad35600e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -400,12 +400,10 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) m_windowFlags = flags; } -Qt::WindowState QCocoaWindow::setWindowState(Qt::WindowState state) +void QCocoaWindow::setWindowState(Qt::WindowState state) { if ([m_nsWindow isVisible]) syncWindowState(state); // Window state set for hidden windows take effect when show() is called. - - return state; } void QCocoaWindow::setWindowTitle(const QString &title) @@ -429,6 +427,26 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath) [m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""]; } +void QCocoaWindow::setWindowIcon(const QIcon &icon) +{ + QCocoaAutoReleasePool pool; + + NSButton *iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton]; + if (iconButton == nil) { + NSString *title = QCFString::toNSString(window()->windowTitle()); + [m_nsWindow setRepresentedURL:[NSURL fileURLWithPath:title]]; + iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton]; + } + if (icon.isNull()) { + [iconButton setImage:nil]; + } else { + QPixmap pixmap = icon.pixmap(QSize(22, 22)); + NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap)); + [iconButton setImage:image]; + [image release]; + } +} + void QCocoaWindow::raise() { //qDebug() << "raise" << this; @@ -695,6 +713,7 @@ void QCocoaWindow::setNSWindow(NSWindow *window) void QCocoaWindow::clearNSWindow(NSWindow *window) { + [window setContentView:nil]; [window setDelegate:nil]; [window clearPlatformWindow]; [[NSNotificationCenter defaultCenter] removeObserver:m_contentView]; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index f23fd3045f..33d0fb4bae 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -89,6 +89,14 @@ static QTouchDevice *touchDevice = 0; return self; } +- (void)dealloc +{ + CGImageRelease(m_cgImage); + m_cgImage = 0; + m_window = 0; + [super dealloc]; +} + - (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow { self = [self init]; @@ -129,22 +137,29 @@ static QTouchDevice *touchDevice = 0; - (void)updateGeometry { - NSRect rect = [self frame]; - NSRect windowRect = [[self window] frame]; - QRect geo(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height); + QRect geometry; + if (m_platformWindow->m_nsWindow) { + // top level window, get window rect and flip y. + NSRect rect = [self frame]; + NSRect windowRect = [[self window] frame]; + geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height); + } else { + // child window, use the frame rect + geometry = qt_mac_toQRect([self frame]); + } #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG - qDebug() << "QNSView::udpateGeometry" << geo; + qDebug() << "QNSView::udpateGeometry" << m_platformWindow << geometry; #endif // Call setGeometry on QPlatformWindow. (not on QCocoaWindow, // doing that will initiate a geometry change it and possibly create // an infinite loop when this notification is triggered again.) - m_platformWindow->QPlatformWindow::setGeometry(geo); + m_platformWindow->QPlatformWindow::setGeometry(geometry); // Send a geometry change event to Qt, if it's ready to handle events if (!m_platformWindow->m_inConstructor) { - QWindowSystemInterface::handleGeometryChange(m_window, geo); + QWindowSystemInterface::handleGeometryChange(m_window, geometry); QWindowSystemInterface::flushWindowSystemEvents(); } } @@ -343,11 +358,15 @@ static QTouchDevice *touchDevice = 0; } NSWindow *window = [self window]; - int windowHeight = [window frame].size.height; NSPoint windowPoint = [theEvent locationInWindow]; + + int windowScreenY = [window frame].origin.y + [window frame].size.height; + int viewScreenY = [window convertBaseToScreen:[self convertPoint:[self frame].origin toView:nil]].y; + int titleBarHeight = windowScreenY - viewScreenY; + NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; - QPoint qtWindowPoint = QPoint(nsViewPoint.x, windowHeight - nsViewPoint.y); - NSPoint screenPoint = [window convertBaseToScreen : windowPoint]; + QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y); + NSPoint screenPoint = [window convertBaseToScreen:windowPoint]; QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); ulong timestamp = [theEvent timestamp] * 1000; diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 9822262127..036b26a165 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -117,10 +117,9 @@ void QEglFSWindow::setGeometry(const QRect &) QPlatformWindow::setGeometry(rect); } -Qt::WindowState QEglFSWindow::setWindowState(Qt::WindowState) +void QEglFSWindow::setWindowState(Qt::WindowState) { setGeometry(QRect()); - return Qt::WindowFullScreen; } WId QEglFSWindow::winId() const diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index c9ef60ac9c..40a38fcb26 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -56,7 +56,7 @@ public: ~QEglFSWindow(); void setGeometry(const QRect &); - Qt::WindowState setWindowState(Qt::WindowState state); + void setWindowState(Qt::WindowState state); WId winId() const; EGLSurface surface() const { return m_surface; } diff --git a/src/plugins/platforms/qnx/qqnxsystemsettings.cpp b/src/plugins/platforms/qnx/qqnxsystemsettings.cpp index ae7cb67314..6194a61012 100644 --- a/src/plugins/platforms/qnx/qqnxsystemsettings.cpp +++ b/src/plugins/platforms/qnx/qqnxsystemsettings.cpp @@ -48,11 +48,13 @@ QT_BEGIN_NAMESPACE QHash<QPlatformTheme::Font, QFont *> qt_qnx_createRoleFonts(QPlatformFontDatabase *fontDatabase) { - // See http://docs.blackberry.com/en/developers/deliverables/27299/Text_tablet_1526156_11.jsp - // which recommends using normal font size of 21 pixels and 36 pixels for titles (not covered - // by the theme system). + // See http://docs.blackberry.com/en/developers/deliverables/41577/typography.jsp + // which recommends using + // - small font size of 6 points + // - normal font size of 8 points + // - 11 points for titles (not covered by the theme system). QFont baseFont = fontDatabase->defaultFont(); - baseFont.setPixelSize(21); + baseFont.setPointSize(8); QHash<QPlatformTheme::Font, QFont *> fonts; fonts.insert(QPlatformTheme::SystemFont, new QFont(baseFont)); @@ -70,7 +72,7 @@ QHash<QPlatformTheme::Font, QFont *> qt_qnx_createRoleFonts(QPlatformFontDatabas fonts.insert(QPlatformTheme::ComboLineEditFont, new QFont(baseFont)); QFont smallFont(baseFont); - smallFont.setPixelSize(15); + smallFont.setPointSize(6); fonts.insert(QPlatformTheme::SmallFont, new QFont(smallFont)); fonts.insert(QPlatformTheme::MiniFont, new QFont(smallFont)); diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 9dd8ad7a71..097b5788f6 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -580,13 +580,13 @@ void QQnxWindow::requestActivateWindow() } -Qt::WindowState QQnxWindow::setWindowState(Qt::WindowState state) +void QQnxWindow::setWindowState(Qt::WindowState state) { qWindowDebug() << Q_FUNC_INFO << "state =" << state; // Prevent two calls with Qt::WindowFullScreen from changing m_unmaximizedGeometry if (m_windowState == state) - return state; + return; switch (state) { @@ -594,7 +594,7 @@ Qt::WindowState QQnxWindow::setWindowState(Qt::WindowState state) // WindowActive is not an accepted parameter according to the docs case Qt::WindowMinimized: case Qt::WindowActive: - return m_windowState; + return; case Qt::WindowMaximized: case Qt::WindowFullScreen: @@ -609,7 +609,6 @@ Qt::WindowState QQnxWindow::setWindowState(Qt::WindowState state) } m_windowState = state; - return state; } void QQnxWindow::gainedFocus() diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index d79c6785dd..90226bb9a4 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -101,7 +101,7 @@ public: void raise(); void lower(); void requestActivateWindow(); - Qt::WindowState setWindowState(Qt::WindowState state); + void setWindowState(Qt::WindowState state); void gainedFocus(); diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp index d337234671..7557b80191 100644 --- a/src/plugins/platforms/windows/main.cpp +++ b/src/plugins/platforms/windows/main.cpp @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE \section1 Tips \list - \li The environment variable \c QT_LIGHTHOUSE_WINDOWS_VERBOSE controls + \li The environment variable \c QT_QPA_VERBOSE controls the debug level. It takes the form \c{<keyword1>:<level1>,<keyword2>:<level2>}, where keyword is one of \c integration, \c windows, \c backingstore and @@ -112,9 +112,8 @@ public: QPlatformIntegration *QWindowsIntegrationPlugin::create(const QString& system, const QStringList& paramList) { - Q_UNUSED(paramList); if (system.compare(system, QStringLiteral("windows"), Qt::CaseInsensitive) == 0) - return new QWindowsIntegration; + return new QWindowsIntegration(paramList); return 0; } diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h index f5ea2cf6bf..a35a513579 100644 --- a/src/plugins/platforms/windows/qtwindows_additional.h +++ b/src/plugins/platforms/windows/qtwindows_additional.h @@ -83,6 +83,21 @@ #define CHILDID_SELF 0 #define WM_GETOBJECT 0x003D +#ifndef SHGFI_ADDOVERLAYS // Shell structures for icons. +typedef struct _SHSTOCKICONINFO +{ + DWORD cbSize; + HICON hIcon; + int iSysImageIndex; + int iIcon; + WCHAR szPath[MAX_PATH]; +} SHSTOCKICONINFO; + +# define SIID_SHIELD 77 +# define SHGFI_ADDOVERLAYS 0x20 +# define SHGFI_OVERLAYINDEX 0x40 +#endif // SIID_SHIELD + #if !defined(__MINGW64_VERSION_MAJOR) #define STATE_SYSTEM_HASPOPUP 0x40000000 diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 98c17deba9..3d4871d7a2 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -210,7 +210,9 @@ bool QWindowsUser32DLL::initTouch() \ingroup qt-lighthouse-win */ -QWindowsShell32DLL::QWindowsShell32DLL() : sHCreateItemFromParsingName(0) +QWindowsShell32DLL::QWindowsShell32DLL() + : sHCreateItemFromParsingName(0) + , sHGetStockIconInfo(0) { } @@ -218,6 +220,7 @@ void QWindowsShell32DLL::init() { QSystemLibrary library(QStringLiteral("shell32")); sHCreateItemFromParsingName = (SHCreateItemFromParsingName)(library.resolve("SHCreateItemFromParsingName")); + sHGetStockIconInfo = (SHGetStockIconInfo)library.resolve("SHGetStockIconInfo"); } QWindowsUser32DLL QWindowsContext::user32dll; diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 450d6c8f4b..dcc636bfc0 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -49,6 +49,7 @@ #include <QtCore/QSharedPointer> struct IBindCtx; +struct _SHSTOCKICONINFO; QT_BEGIN_NAMESPACE @@ -99,8 +100,10 @@ struct QWindowsShell32DLL inline void init(); typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **); + typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *); SHCreateItemFromParsingName sHCreateItemFromParsingName; + SHGetStockIconInfo sHGetStockIconInfo; }; #endif // Q_OS_WINCE @@ -115,7 +118,7 @@ public: SI_SupportsTouch = 0x2 }; - // Verbose flag set by environment variable QT_LIGHTHOUSE_WINDOWS_VERBOSE + // Verbose flag set by environment variable QT_QPA_VERBOSE static int verboseIntegration; static int verboseWindows; static int verboseBackingStore; diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 1c9a7d36f5..b50a858f96 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -42,6 +42,7 @@ #include "qwindowsglcontext.h" #include "qwindowscontext.h" #include "qwindowswindow.h" +#include "qwindowsintegration.h" #include <QtCore/QDebug> #include <QtCore/QSysInfo> @@ -439,7 +440,7 @@ static int choosePixelFormat(HDC hdc, iAttributes[i++] = WGL_SAMPLES_ARB; samplesValuePosition = i; iAttributes[i++] = format.samples(); - } else if (samples == 0 || samples == 1 ) { + } else { iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; iAttributes[i++] = FALSE; } @@ -855,16 +856,6 @@ QDebug operator<<(QDebug d, const QOpenGLStaticContext &s) return d; } -// Use ARB unless explicitly turned off on command line. -static inline bool useARB() -{ - const QVariant glExtension = qApp->platformNativeInterface()->property("gl"); - if (glExtension.type() == QVariant::String - && !glExtension.toString().compare(QStringLiteral("gdi"), Qt::CaseInsensitive)) - return false; - return true; -} - /*! \class QWindowsGLContext \brief Open GL context. @@ -914,12 +905,13 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex if (QWindowsContext::verboseGL > 1) describeFormats(hdc); - // Preferably use direct rendering and ARB extensions (unless pixmap) + // Preferably use direct rendering and ARB extensions (unless pixmap + // or explicitly turned off on command line). const QWindowsOpenGLAdditionalFormat requestedAdditional(QWindowsGLDirectRendering); tryExtensions = m_staticContext->hasExtensions() && !testFlag(requestedAdditional.formatFlags, QWindowsGLRenderToPixmap) - && useARB(); + && !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DisableArb); QWindowsOpenGLAdditionalFormat obtainedAdditional; if (tryExtensions) { m_pixelFormat = diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 1f26ec5bab..50ffb85b01 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -187,6 +187,40 @@ void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTempl \class QWindowsIntegration \brief QPlatformIntegration implementation for Windows. \internal + + \section1 Programming Considerations + + The platform plugin should run on Desktop Windows from Windows XP onwards + and Windows Embedded. + + It should compile with: + \list + \li Microsoft Visual Studio 2008 or later (using the Microsoft Windows SDK, + (\c Q_CC_MSVC). + \li Stock \l{http://mingw.org/}{MinGW} (\c Q_CC_MINGW). + This version ships with headers that are missing a lot of WinAPI. + \li MinGW distributions using GCC 4.7 or higher and a recent MinGW-w64 runtime API, + such as \l{http://tdm-gcc.tdragon.net/}{TDM-GCC}, or + \l{http://mingwbuilds.sourceforge.net/}{MinGW-builds} + (\c Q_CC_MINGW and \c __MINGW64_VERSION_MAJOR indicating the version). + MinGW-w64 provides more complete headers (compared to stock MinGW from mingw.org), + including a considerable part of the Windows SDK. + \li Visual Studio 2008 for Windows Embedded (\c Q_OS_WINCE). + \endlist + + The file \c qtwindows_additional.h contains defines and declarations that + are missing in MinGW. When encountering missing declarations, it should + be added there so that \c #ifdefs for MinGW can be avoided. Similarly, + \c qplatformfunctions_wince.h contains defines and declarations for + Windows Embedded. + + When using a function from the WinAPI, the minimum supported Windows version + and Windows Embedded support should be checked. If the function is not supported + on Windows XP or is not present in the MinGW-headers, it should be dynamically + resolved. For this purpose, QWindowsContext has static structs like + QWindowsUser32DLL and QWindowsShell32DLL. All function pointers should go to + these structs to avoid lookups in several places. + \ingroup qt-lighthouse-win */ @@ -198,9 +232,10 @@ struct QWindowsIntegrationPrivate typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr; #endif - QWindowsIntegrationPrivate(); + explicit QWindowsIntegrationPrivate(const QStringList ¶mList); ~QWindowsIntegrationPrivate(); + const unsigned m_options; QWindowsContext m_context; QPlatformFontDatabase *m_fontDatabase; QWindowsNativeInterface m_nativeInterface; @@ -221,8 +256,27 @@ struct QWindowsIntegrationPrivate QWindowsServices m_services; }; -QWindowsIntegrationPrivate::QWindowsIntegrationPrivate() - : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher) +static inline unsigned parseOptions(const QStringList ¶mList) +{ + unsigned options = 0; + foreach (const QString ¶m, paramList) { + if (param.startsWith(QLatin1String("fontengine="))) { + if (param.endsWith(QLatin1String("freetype"))) { + options |= QWindowsIntegration::FontDatabaseFreeType; + } else if (param.endsWith(QLatin1String("native"))) { + options |= QWindowsIntegration::FontDatabaseNative; + } + } else if (param == QLatin1String("gl=gdi")) { + options |= QWindowsIntegration::DisableArb; + } + } + return options; +} + +QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mList) + : m_options(parseOptions(paramList)) + , m_fontDatabase(0) + , m_eventDispatcher(new QWindowsGuiEventDispatcher) { } @@ -232,8 +286,8 @@ QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate() delete m_fontDatabase; } -QWindowsIntegration::QWindowsIntegration() : - d(new QWindowsIntegrationPrivate) +QWindowsIntegration::QWindowsIntegration(const QStringList ¶mList) : + d(new QWindowsIntegrationPrivate(paramList)) { QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher); #ifndef QT_NO_CLIPBOARD @@ -337,25 +391,6 @@ QPlatformOpenGLContext /* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for * QML2 applications. */ -enum FontDatabaseOption { - FontDatabaseFreeType, - FontDatabaseNative, - FontDatabaseAuto -}; - -static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface) -{ - const QVariant argumentV = nativeInterface.property("fontengine"); - if (argumentV.isValid()) { - const QString argument = argumentV.toString(); - if (argument == QLatin1String("freetype")) - return FontDatabaseFreeType; - if (argument == QLatin1String("native")) - return FontDatabaseNative; - } - return FontDatabaseAuto; -} - #ifdef Q_OS_WINCE // It's not easy to detect if we are running a QML application // Let's try to do so by checking if the QtQuick module is loaded. @@ -377,10 +412,9 @@ QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const #ifdef QT_NO_FREETYPE d->m_fontDatabase = new QWindowsFontDatabase(); #else // QT_NO_FREETYPE - FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface); - if (option == FontDatabaseFreeType) { + if (d->m_options & QWindowsIntegration::FontDatabaseFreeType) { d->m_fontDatabase = new QWindowsFontDatabaseFT; - } else if (option == FontDatabaseNative){ + } else if (d->m_options & QWindowsIntegration::FontDatabaseNative){ d->m_fontDatabase = new QWindowsFontDatabase; } else { #ifndef Q_OS_WINCE @@ -486,6 +520,11 @@ QWindowsIntegration *QWindowsIntegration::instance() return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration()); } +unsigned QWindowsIntegration::options() const +{ + return d->m_options; +} + QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const { return d->m_eventDispatcher; diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 49780566dd..ca47dabb4b 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -53,7 +53,13 @@ struct QWindowsIntegrationPrivate; class QWindowsIntegration : public QPlatformIntegration { public: - QWindowsIntegration(); + enum Options { // Options to be passed on command line. + FontDatabaseFreeType = 0x1, + FontDatabaseNative = 0x2, + DisableArb = 0x4 + }; + + explicit QWindowsIntegration(const QStringList ¶mList); virtual ~QWindowsIntegration(); bool hasCapability(QPlatformIntegration::Capability cap) const; @@ -87,6 +93,8 @@ public: inline void emitScreenAdded(QPlatformScreen *s) { screenAdded(s); } + unsigned options() const; + private: QScopedPointer<QWindowsIntegrationPrivate> d; }; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index b57a27acb4..c11bd8c53c 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -68,7 +68,6 @@ QWindowsKeyMapper::QWindowsKeyMapper() QWindowsKeyMapper::~QWindowsKeyMapper() { - deleteLayouts(); } #ifndef LANG_PASHTO @@ -436,6 +435,8 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 Qt::NoModifier, // Fall-back to raw Key_* }; +static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl; +Q_STATIC_ASSERT((NumMods == KeyboardLayoutItem::NumQtKeys)); /** Remap return or action key to select key for windows mobile. @@ -520,32 +521,10 @@ static inline bool isModifierKey(int code) // Keyboard map private ----------------------------------------------------------------[ start ]--- -/* - \internal - A Windows KeyboardLayoutItem has 8 possible states: - 1. Unmodified - 2. Shift - 3. Control - 4. Control + Shift - 5. Alt - 6. Alt + Shift - 7. Alt + Control - 8. Alt + Control + Shift -*/ -struct KeyboardLayoutItem { - bool dirty; - quint8 deadkeys; - quint32 qtKey[9]; // Can by any Qt::Key_<foo>, or unicode character -}; - void QWindowsKeyMapper::deleteLayouts() { - for (int i = 0; i < 255; ++i) { - if (keyLayout[i]) { - delete keyLayout[i]; - keyLayout[i] = 0; - } - } + for (size_t i = 0; i < NumKeyboardLayoutItems; ++i) + keyLayout[i].exists = false; } void QWindowsKeyMapper::changeKeyboard() @@ -594,12 +573,9 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg) void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode, quint32 vk_key) { - if (!vk_key || (keyLayout[vk_key] && !keyLayout[vk_key]->dirty)) + if (!vk_key || (keyLayout[vk_key].exists && !keyLayout[vk_key].dirty)) return; - if (!keyLayout[vk_key]) - keyLayout[vk_key] = new KeyboardLayoutItem; - // Copy keyboard state, so we can modify and query output for each possible permutation unsigned char buffer[256]; memcpy(buffer, kbdBuffer, sizeof(buffer)); @@ -615,40 +591,41 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 buffer[VK_LMENU ] = 0; // Use right Alt, since left Ctrl + right Alt is considered AltGraph bool isDeadKey = false; - keyLayout[vk_key]->deadkeys = 0; - keyLayout[vk_key]->dirty = false; + keyLayout[vk_key].deadkeys = 0; + keyLayout[vk_key].dirty = false; + keyLayout[vk_key].exists = true; setKbdState(buffer, false, false, false); - keyLayout[vk_key]->qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x01 : 0; + keyLayout[vk_key].qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x01 : 0; setKbdState(buffer, true, false, false); - keyLayout[vk_key]->qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x02 : 0; + keyLayout[vk_key].qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x02 : 0; setKbdState(buffer, false, true, false); - keyLayout[vk_key]->qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x04 : 0; + keyLayout[vk_key].qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x04 : 0; setKbdState(buffer, true, true, false); - keyLayout[vk_key]->qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x08 : 0; + keyLayout[vk_key].qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x08 : 0; setKbdState(buffer, false, false, true); - keyLayout[vk_key]->qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x10 : 0; + keyLayout[vk_key].qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x10 : 0; setKbdState(buffer, true, false, true); - keyLayout[vk_key]->qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x20 : 0; + keyLayout[vk_key].qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x20 : 0; setKbdState(buffer, false, true, true); - keyLayout[vk_key]->qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x40 : 0; + keyLayout[vk_key].qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x40 : 0; setKbdState(buffer, true, true, true); - keyLayout[vk_key]->qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x80 : 0; + keyLayout[vk_key].qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x80 : 0; // Add a fall back key for layouts which don't do composition and show non-latin1 characters int fallbackKey = winceKeyBend(vk_key); if (!fallbackKey || fallbackKey == Qt::Key_unknown) { fallbackKey = 0; - if (vk_key != keyLayout[vk_key]->qtKey[0] && vk_key < 0x5B && vk_key > 0x2F) + if (vk_key != keyLayout[vk_key].qtKey[0] && vk_key < 0x5B && vk_key > 0x2F) fallbackKey = vk_key; } - keyLayout[vk_key]->qtKey[8] = fallbackKey; + keyLayout[vk_key].qtKey[8] = fallbackKey; // If this vk_key a Dead Key if (MapVirtualKey(vk_key, 2) & 0x80000000) { @@ -666,22 +643,22 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 if (QWindowsContext::verboseEvents > 1) { qDebug("updatePossibleKeyCodes for virtual key = 0x%02x!", vk_key); - for (int i = 0; i < 9; ++i) { - qDebug(" [%d] (%d,0x%02x,'%c') %s", i, - keyLayout[vk_key]->qtKey[i], - keyLayout[vk_key]->qtKey[i], - keyLayout[vk_key]->qtKey[i] ? keyLayout[vk_key]->qtKey[i] : 0x03, - keyLayout[vk_key]->deadkeys & (1<<i) ? "deadkey" : ""); + for (size_t i = 0; i < NumMods; ++i) { + qDebug(" [%d] (%d,0x%02x,'%c') %s", int(i), + keyLayout[vk_key].qtKey[i], + keyLayout[vk_key].qtKey[i], + keyLayout[vk_key].qtKey[i] ? keyLayout[vk_key].qtKey[i] : 0x03, + keyLayout[vk_key].deadkeys & (1<<i) ? "deadkey" : ""); } } } bool QWindowsKeyMapper::isADeadKey(unsigned int vk_key, unsigned int modifiers) { - if (keyLayout && (vk_key < 256) && keyLayout[vk_key]) { - for (register int i = 0; i < 9; ++i) { + if ((vk_key < NumKeyboardLayoutItems) && keyLayout[vk_key].exists) { + for (register size_t i = 0; i < NumMods; ++i) { if (uint(ModsTbl[i]) == modifiers) - return bool(keyLayout[vk_key]->deadkeys & 1<<i); + return bool(keyLayout[vk_key].deadkeys & 1<<i); } } return false; @@ -1123,11 +1100,11 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const { QList<int> result; - KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()]; - if (!kbItem) + const KeyboardLayoutItem &kbItem = keyLayout[e->nativeVirtualKey()]; + if (!kbItem.exists) return result; - quint32 baseKey = kbItem->qtKey[0]; + quint32 baseKey = kbItem.qtKey[0]; Qt::KeyboardModifiers keyMods = e->modifiers(); if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) { result << int(Qt::Key_Enter + keyMods); @@ -1135,9 +1112,9 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const } result << int(baseKey + keyMods); // The base key is _always_ valid, of course - for (int i = 1; i < 9; ++i) { + for (int i = 1; i < NumMods; ++i) { Qt::KeyboardModifiers neededMods = ModsTbl[i]; - quint32 key = kbItem->qtKey[i]; + quint32 key = kbItem.qtKey[i]; if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) result << int(key + (keyMods & ~neededMods)); } diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h index 7b3f18a42d..6de255facf 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.h +++ b/src/plugins/platforms/windows/qwindowskeymapper.h @@ -51,7 +51,25 @@ QT_BEGIN_NAMESPACE class QKeyEvent; class QWindow; -struct KeyboardLayoutItem; +/* + \internal + A Windows KeyboardLayoutItem has 8 possible states: + 1. Unmodified + 2. Shift + 3. Control + 4. Control + Shift + 5. Alt + 6. Alt + Shift + 7. Alt + Control + 8. Alt + Control + Shift +*/ +struct KeyboardLayoutItem { + uint dirty : 1; + uint exists : 1; // whether this item has been initialized (by updatePossibleKeyCodes) + quint8 deadkeys; + static const size_t NumQtKeys = 9; + quint32 qtKey[NumQtKeys]; // Can by any Qt::Key_<foo>, or unicode character +}; class QWindowsKeyMapper { @@ -87,8 +105,9 @@ private: bool isADeadKey(unsigned int vk_key, unsigned int modifiers); void deleteLayouts(); - KeyboardLayoutItem *keyLayout[256]; QWindow *m_keyGrabber; + static const size_t NumKeyboardLayoutItems = 256; + KeyboardLayoutItem keyLayout[NumKeyboardLayoutItems]; }; enum WindowsNativeModifiers { diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 7b3ffc633f..d9de911914 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -55,9 +55,13 @@ #include <QtCore/QDebug> #include <QtCore/QTextStream> #include <QtCore/QSysInfo> +#include <QtCore/QCache> #include <QtGui/QPalette> #include <QtGui/QGuiApplication> +#include <QtGui/QPainter> +#include <QtGui/QPixmapCache> #include <qpa/qwindowsysteminterface.h> +#include <private/qsystemlibrary_p.h> QT_BEGIN_NAMESPACE @@ -348,6 +352,11 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const return QVariant(int(WindowsKeyboardScheme)); case UiEffects: return QVariant(uiEffects()); + case IconPixmapSizes: { + QList<int> sizes; + sizes << 16 << 32; + return QVariant::fromValue(sizes); + } default: break; } @@ -433,4 +442,225 @@ void QWindowsTheme::windowsThemeChanged(QWindow * window) QWindowSystemInterface::handleThemeChange(window); } +// Defined in qpixmap_win.cpp +Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon); + +static QPixmap loadIconFromShell32(int resourceId, QSizeF size) +{ +#ifdef Q_OS_WINCE + HMODULE hmod = LoadLibrary(L"ceshell"); +#else + HMODULE hmod = QSystemLibrary::load(L"shell32"); +#endif + if (hmod) { + HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size.width(), size.height(), 0); + if (iconHandle) { + QPixmap iconpixmap = qt_pixmapFromWinHICON(iconHandle); + DestroyIcon(iconHandle); + return iconpixmap; + } + } + return QPixmap(); +} + +QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const +{ + int resourceId = -1; + LPCTSTR iconName = 0; + switch (sp) { + case DriveCDIcon: + case DriveDVDIcon: + resourceId = 12; + break; + case DriveNetIcon: + resourceId = 10; + break; + case DriveHDIcon: + resourceId = 9; + break; + case DriveFDIcon: + resourceId = 7; + break; + case FileIcon: + case FileLinkIcon: + resourceId = 1; + break; + case DirIcon: + case DirLinkIcon: + case DirClosedIcon: + resourceId = 4; + break; + case DesktopIcon: + resourceId = 35; + break; + case ComputerIcon: + resourceId = 16; + break; + case DirOpenIcon: + case DirLinkOpenIcon: + resourceId = 5; + break; + case FileDialogNewFolder: + resourceId = 319; + break; + case DirHomeIcon: + resourceId = 235; + break; + case TrashIcon: + resourceId = 191; + break; + case MessageBoxInformation: + iconName = IDI_INFORMATION; + break; + case MessageBoxWarning: + iconName = IDI_WARNING; + break; + case MessageBoxCritical: + iconName = IDI_ERROR; + break; + case MessageBoxQuestion: + iconName = IDI_QUESTION; + break; + case VistaShield: + if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA + && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) { + if (!QWindowsContext::shell32dll.sHGetStockIconInfo) + return QPixmap(); + QPixmap pixmap; + SHSTOCKICONINFO iconInfo; + memset(&iconInfo, 0, sizeof(iconInfo)); + iconInfo.cbSize = sizeof(iconInfo); + const int iconSize = size.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON; + if (QWindowsContext::shell32dll.sHGetStockIconInfo(SIID_SHIELD, SHGFI_ICON | iconSize, &iconInfo) == S_OK) { + pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon); + DestroyIcon(iconInfo.hIcon); + return pixmap; + } + } + break; + default: + break; + } + + if (resourceId != -1) { + QPixmap pixmap = loadIconFromShell32(resourceId, size); + if (!pixmap.isNull()) { + if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) { + QPainter painter(&pixmap); + QPixmap link = loadIconFromShell32(30, size); + painter.drawPixmap(0, 0, size.width(), size.height(), link); + } + return pixmap; + } + } + + if (iconName) { + HICON iconHandle = LoadIcon(NULL, iconName); + QPixmap pixmap = qt_pixmapFromWinHICON(iconHandle); + DestroyIcon(iconHandle); + if (!pixmap.isNull()) + return pixmap; + } + + return QPlatformTheme::standardPixmap(sp, size); +} + +static QString dirIconPixmapCacheKey(int iIcon, int iconSize) +{ + QString key = QLatin1String("qt_dir_") + QString::number(iIcon); + if (iconSize == SHGFI_LARGEICON) + key += QLatin1Char('l'); + return key; +} + +template <typename T> +class FakePointer +{ +public: + + Q_STATIC_ASSERT_X(sizeof(T) <= sizeof(void *), "FakePointers can only go that far."); + + static FakePointer *create(T thing) + { + return reinterpret_cast<FakePointer *>(thing); + } + + T operator * () const + { + return T(qintptr(this)); + } + + void operator delete (void *) {} +}; + +QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const +{ + /* We don't use the variable, but by storing it statically, we + * ensure CoInitialize is only called once. */ + static HRESULT comInit = CoInitialize(NULL); + Q_UNUSED(comInit); + + static QCache<QString, FakePointer<int> > dirIconEntryCache(1000); + static QMutex mx; + + QPixmap pixmap; + const QString filePath = QDir::toNativeSeparators(fileInfo.filePath()); + int iconSize = size.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON; + + bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot(); + if (cacheableDirIcon) { + QMutexLocker locker(&mx); + int iIcon = **dirIconEntryCache.object(filePath); + if (iIcon) { + QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize), pixmap); + if (pixmap.isNull()) // Let's keep both caches in sync + dirIconEntryCache.remove(filePath); + else + return pixmap; + } + } + + SHFILEINFO info; + unsigned int flags = +#ifndef Q_OS_WINCE + SHGFI_ICON|iconSize|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX; +#else + iconSize|SHGFI_SYSICONINDEX; +#endif // Q_OS_WINCE + unsigned long val = SHGetFileInfo((const wchar_t *)filePath.utf16(), 0, + &info, sizeof(SHFILEINFO), flags); + + // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases + if (val && info.hIcon) { + QString key; + if (cacheableDirIcon) { + //using the unique icon index provided by windows save us from duplicate keys + key = dirIconPixmapCacheKey(info.iIcon, iconSize); + QPixmapCache::find(key, pixmap); + if (!pixmap.isNull()) { + QMutexLocker locker(&mx); + dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon)); + } + } + + if (pixmap.isNull()) { + pixmap = qt_pixmapFromWinHICON(info.hIcon); + if (!pixmap.isNull()) { + if (cacheableDirIcon) { + QMutexLocker locker(&mx); + QPixmapCache::insert(key, pixmap); + dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon)); + } + } else { + qWarning("QWindowsTheme::fileIconPixmap() no icon found"); + } + } + DestroyIcon(info.hIcon); + } + + if (!pixmap.isNull()) + return pixmap; + return QPlatformTheme::fileIconPixmap(fileInfo, size); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index 7e885b8f3e..89ef527e76 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -67,6 +67,9 @@ public: virtual const QFont *font(Font type = SystemFont) const { return m_fonts[type]; } + virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const; + virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const; + void windowsThemeChanged(QWindow *window); static const char *name; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f3830eb962..99b8922768 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE +Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &); + static QByteArray debugWinStyle(DWORD style) { QByteArray rc = "0x"; @@ -699,13 +701,15 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()), m_dropTarget(0), m_savedStyle(0), - m_format(aWindow->format()) + m_format(aWindow->format()), #ifdef QT_OPENGL_ES_2 - , m_eglSurface(0) + m_eglSurface(0), #endif #ifdef Q_OS_WINCE - , m_previouslyHidden(false) + m_previouslyHidden(false), #endif + m_iconSmall(0), + m_iconBig(0) { if (aWindow->surfaceType() == QWindow::OpenGLSurface) setFlag(OpenGLSurface); @@ -730,6 +734,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : QWindowsWindow::~QWindowsWindow() { destroyWindow(); + destroyIcon(); } void QWindowsWindow::destroyWindow() @@ -1230,13 +1235,12 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state) QWindowSystemInterface::handleWindowStateChanged(window(), state); } -Qt::WindowState QWindowsWindow::setWindowState(Qt::WindowState state) +void QWindowsWindow::setWindowState(Qt::WindowState state) { if (m_data.hwnd) { setWindowState_sys(state); m_windowState = state; } - return state; } bool QWindowsWindow::isFullScreen_sys() const @@ -1754,4 +1758,32 @@ QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf) return rc; } +static HICON createHIcon(const QIcon &icon, int xSize, int ySize) +{ + if (!icon.isNull()) { + const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize))); + if (!pm.isNull()) + return qt_pixmapToWinHICON(pm); + } + return 0; +} + +void QWindowsWindow::setWindowIcon(const QIcon &icon) +{ + if (m_data.hwnd) { + destroyIcon(); + + m_iconSmall = createHIcon(icon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); + m_iconBig = createHIcon(icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); + + if (m_iconBig) { + SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)m_iconSmall); + SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)m_iconBig); + } else { + SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)m_iconSmall); + SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)m_iconSmall); + } + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 3b7666cf32..978d1d5a53 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -160,7 +160,7 @@ public: virtual QPoint mapFromGlobal(const QPoint &pos) const; virtual void setWindowFlags(Qt::WindowFlags flags); - virtual Qt::WindowState setWindowState(Qt::WindowState state); + virtual void setWindowState(Qt::WindowState state); HWND handle() const { return m_data.hwnd; } @@ -238,6 +238,7 @@ public: void setEnabled(bool enabled); bool isEnabled() const; + void setWindowIcon(const QIcon &icon); #ifndef Q_OS_WINCE void alertWindow(int durationMs = 0); @@ -259,6 +260,7 @@ private: void unregisterDropSite(); void handleGeometryChange(); void handleWindowStateChange(Qt::WindowState state); + inline void destroyIcon(); mutable WindowData m_data; mutable unsigned m_flags; @@ -277,6 +279,8 @@ private: #ifdef Q_OS_WINCE bool m_previouslyHidden; #endif + HICON m_iconSmall; + HICON m_iconBig; }; // Conveniences for window frames. @@ -346,6 +350,18 @@ void QWindowsWindow::setUserDataOf(HWND hwnd, void *ud) SetWindowLongPtr(hwnd, GWLP_USERDATA, LONG_PTR(ud)); } +inline void QWindowsWindow::destroyIcon() +{ + if (m_iconBig) { + DestroyIcon(m_iconBig); + m_iconBig = 0; + } + if (m_iconSmall) { + DestroyIcon(m_iconSmall); + m_iconSmall = 0; + } +} + QT_END_NAMESPACE #endif // QWINDOWSWINDOW_H diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index 6254d68ae8..264d28c6b4 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -9,3 +9,7 @@ The packages for xcb-render-util can be installed manually from http://packages. On Ubuntu 12.04 icccm1 is replaced by icccm4 and xcb-render-util can be installed automatically: libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0 libxcb-render-util0-dev + + +On Fedora, the following packages are required: +libxcb libxcb-devel libXrender libXrender-devel xcb-util-wm xcb-util-wm-devel xcb-util xcb-util-devel xcb-util-image xcb-util-image-devel xcb-util-keysyms xcb-util-keysyms-devel diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index cefe1a7786..bab1884a9a 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -847,10 +847,10 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); } -Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state) +void QXcbWindow::setWindowState(Qt::WindowState state) { if (state == m_windowState) - return state; + return; // unset old state switch (m_windowState) { @@ -905,7 +905,6 @@ Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state) connection()->sync(); m_windowState = state; - return m_windowState; } void QXcbWindow::setNetWmWindowFlags(Qt::WindowFlags flags) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index e2f62401dc..bd4d18a175 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -82,7 +82,7 @@ public: void setVisible(bool visible); void setWindowFlags(Qt::WindowFlags flags); - Qt::WindowState setWindowState(Qt::WindowState state); + void setWindowState(Qt::WindowState state); WId winId() const; void setParent(const QPlatformWindow *window); diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h index 88a554dcea..2642ee206a 100644 --- a/src/testlib/qtestaccessible.h +++ b/src/testlib/qtestaccessible.h @@ -218,6 +218,14 @@ private: ev = upd; } else if (event->type() == QAccessible::ValueChanged) { ev = new QAccessibleValueChangeEvent(event->object(), static_cast<QAccessibleValueChangeEvent*>(event)->value()); + } else if (event->type() == QAccessible::TableModelChanged) { + QAccessibleTableModelChangeEvent *oldEvent = static_cast<QAccessibleTableModelChangeEvent*>(event); + QAccessibleTableModelChangeEvent *newEvent = new QAccessibleTableModelChangeEvent(event->object(), oldEvent->modelChangeType()); + newEvent->setFirstRow(oldEvent->firstRow()); + newEvent->setFirstColumn(oldEvent->firstColumn()); + newEvent->setLastRow(oldEvent->lastRow()); + newEvent->setLastColumn(oldEvent->lastColumn()); + ev = newEvent; } else { ev = new QAccessibleEvent(event->object(), event->type()); } diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 7cd83c857d..c56a00237b 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -76,6 +76,14 @@ static void saveCoverageTool(const char * appname, bool testfailed, bool install #endif } +// +// declare deprecated API from qlogging.h locally +// (we can't use qInstallMessageHandler because it would break +// tests that (still) rely on qInstallMsgHandler.) +// +typedef void (*QtMsgHandler)(QtMsgType, const char *); +Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); + namespace QTest { int fails = 0; diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index ffc369fd18..19c0005bcc 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -140,6 +140,6 @@ exists($$QTDIR/.qmake.cache): \ else: \ mod_component_base = $$dirname(_QMAKE_CACHE_) QMAKE_SYNCQT += -minimal -module QtCore -module QtDBus -module QtXml \ - -qtdir $$[QT_HOST_DATA/get] -outdir $$mod_component_base $$dirname(_QMAKE_CONF_) + -mkspecsdir $$[QT_HOST_DATA/get]/mkspecs -outdir $$mod_component_base $$dirname(_QMAKE_CONF_) !silent:message($$QMAKE_SYNCQT) system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT") diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 22a7d50f7c..138b1f9b74 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -75,11 +75,11 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent) #ifndef QT_NO_FILESYSTEMWATCHER watcher(0), #endif - m_resolveSymlinks(false), m_iconProvider(&defaultProvider) -{ #ifdef Q_OS_WIN - m_resolveSymlinks = true; + m_resolveSymlinks(true), #endif + m_iconProvider(&defaultProvider) +{ #ifndef QT_NO_FILESYSTEMWATCHER watcher = new QFileSystemWatcher(this); connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(list(QString))); @@ -108,7 +108,11 @@ void QFileInfoGatherer::setResolveSymlinks(bool enable) bool QFileInfoGatherer::resolveSymlinks() const { +#ifdef Q_OS_WIN return m_resolveSymlinks; +#else + return false; +#endif } void QFileInfoGatherer::setIconProvider(QFileIconProvider *provider) @@ -233,6 +237,7 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const #endif #endif +#ifdef Q_OS_WIN if (fileInfo.isSymLink() && m_resolveSymlinks) { QFileInfo resolvedInfo(fileInfo.symLinkTarget()); resolvedInfo = resolvedInfo.canonicalFilePath(); @@ -240,6 +245,7 @@ QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const emit nameResolved(fileInfo.filePath(), resolvedInfo.fileName()); } } +#endif return info; } diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h index 9837b1aa08..87afbd96bd 100644 --- a/src/widgets/dialogs/qfileinfogatherer_p.h +++ b/src/widgets/dialogs/qfileinfogatherer_p.h @@ -192,7 +192,9 @@ private: #ifndef QT_NO_FILESYSTEMWATCHER QFileSystemWatcher *watcher; #endif +#ifdef Q_OS_WIN bool m_resolveSymlinks; // not accessed by run() +#endif QFileIconProvider *m_iconProvider; // not accessed by run() QFileIconProvider defaultProvider; }; diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index 02088db6c8..375aa9b6ca 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -7575,6 +7575,18 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent QGraphicsItem::d_ptr->isObject = true; } +/*! + \reimp +*/ +bool QGraphicsObject::event(QEvent *ev) +{ + if (ev->type() == QEvent::StyleAnimationUpdate) { + update(); + return true; + } + return QObject::event(ev); +} + #ifndef QT_NO_GESTURES /*! Subscribes the graphics object to the given \a gesture with specific \a flags. diff --git a/src/widgets/graphicsview/qgraphicsitem.h b/src/widgets/graphicsview/qgraphicsitem.h index 93fddd36ca..ce7adfcfad 100644 --- a/src/widgets/graphicsview/qgraphicsitem.h +++ b/src/widgets/graphicsview/qgraphicsitem.h @@ -594,6 +594,9 @@ Q_SIGNALS: protected: QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent); + + bool event(QEvent *ev); + private: friend class QGraphicsItem; friend class QGraphicsItemPrivate; diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 380d58c4be..5c338367f9 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -1597,6 +1597,8 @@ QGraphicsScene *QGraphicsView::scene() const When a scene is set on a view, the QGraphicsScene::changed() signal is automatically connected to this view's updateScene() slot, and the view's scroll bars are adjusted to fit the size of the scene. + + The view does not take ownership of \a scene. */ void QGraphicsView::setScene(QGraphicsScene *scene) { diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp index 99a7c1c929..70750c6006 100644 --- a/src/widgets/itemviews/qfileiconprovider.cpp +++ b/src/widgets/itemviews/qfileiconprovider.cpp @@ -50,6 +50,7 @@ #include <private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> #include <qpa/qplatformservices.h> +#include <qpa/qplatformtheme.h> #if defined(Q_OS_WIN) #if defined(_WIN32_IE) @@ -59,26 +60,14 @@ # include <qt_windows.h> # include <commctrl.h> # include <objbase.h> - -#elif defined(Q_WS_MAC) -# include <private/qt_cocoa_helpers_mac_p.h> #endif #if defined(Q_OS_UNIX) && !defined(QT_NO_STYLE_GTK) # include <private/qgtkstyle_p.h> #endif -#ifndef SHGFI_ADDOVERLAYS -# define SHGFI_ADDOVERLAYS 0x000000020 -# define SHGFI_OVERLAYINDEX 0x000000040 -#endif - QT_BEGIN_NAMESPACE -#if defined (Q_OS_WIN) -Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon); -#endif - /*! \class QFileIconProvider @@ -105,11 +94,8 @@ class QFileIconProviderPrivate public: QFileIconProviderPrivate(); QIcon getIcon(QStyle::StandardPixmap name) const; -#ifdef Q_OS_WIN - QIcon getWinIcon(const QFileInfo &fi) const; -#elif defined(Q_WS_MAC) - QIcon getMacIcon(const QFileInfo &fi) const; -#endif + QIcon getIcon(const QFileInfo &fi) const; + QFileIconProvider *q_ptr; const QString homePath; @@ -238,162 +224,50 @@ QIcon QFileIconProvider::icon(IconType type) const return QIcon(); } -#ifdef Q_OS_WIN -QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const +QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const { QIcon retIcon; - const QString fileExtension = QLatin1Char('.') + fileInfo.suffix().toUpper(); - - QString key; - if (fileInfo.isFile() && !fileInfo.isExecutable() && !fileInfo.isSymLink() && fileExtension != QLatin1String(".ICO")) - key = QLatin1String("qt_") + fileExtension; - - QPixmap pixmap; - if (!key.isEmpty()) { - QPixmapCache::find(key, pixmap); - } - - if (!pixmap.isNull()) { - retIcon.addPixmap(pixmap); - if (QPixmapCache::find(key + QLatin1Char('l'), pixmap)) - retIcon.addPixmap(pixmap); + const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); + if (!theme) return retIcon; - } - - /* We don't use the variable, but by storing it statically, we - * ensure CoInitialize is only called once. */ - static HRESULT comInit = CoInitialize(NULL); - Q_UNUSED(comInit); - SHFILEINFO info; - unsigned long val = 0; + QList<int> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<int> >(); + if (sizes.isEmpty()) + return retIcon; - //Get the small icon -#ifndef Q_OS_WINCE - val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, - sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX); -#else - val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, - sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_SYSICONINDEX); -#endif + const QString fileExtension = fi.suffix().toUpper(); + const QString keyBase = QLatin1String("qt_.") + fi.suffix().toUpper(); - // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases - if (val && info.hIcon) { - if (fileInfo.isDir() && !fileInfo.isRoot()) { - //using the unique icon index provided by windows save us from duplicate keys - key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon); - QPixmapCache::find(key, pixmap); - if (!pixmap.isNull()) { - retIcon.addPixmap(pixmap); - if (QPixmapCache::find(key + QLatin1Char('l'), pixmap)) + bool cacheable = fi.isFile() && !fi.isExecutable() && !fi.isSymLink() && fileExtension != QLatin1String("ICO"); + if (cacheable) { + QPixmap pixmap; + QPixmapCache::find(keyBase + QString::number(sizes.at(0)), pixmap); + if (!pixmap.isNull()) { + bool iconIsComplete = true; + retIcon.addPixmap(pixmap); + for (int i = 1; i < sizes.count(); i++) + if (QPixmapCache::find(keyBase + QString::number(sizes.at(i)), pixmap)) { retIcon.addPixmap(pixmap); - DestroyIcon(info.hIcon); + } else { + iconIsComplete = false; + break; + } + if (iconIsComplete) return retIcon; - } } - if (pixmap.isNull()) { - pixmap = qt_pixmapFromWinHICON(info.hIcon); - if (!pixmap.isNull()) { - retIcon.addPixmap(pixmap); - if (!key.isEmpty()) - QPixmapCache::insert(key, pixmap); - } - else { - qWarning("QFileIconProviderPrivate::getWinIcon() no small icon found"); - } - } - DestroyIcon(info.hIcon); } - //Get the big icon -#ifndef Q_OS_WINCE - val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, - sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX); -#else - val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, - sizeof(SHFILEINFO), SHGFI_LARGEICON|SHGFI_SYSICONINDEX); -#endif - if (val && info.hIcon) { - if (fileInfo.isDir() && !fileInfo.isRoot()) { - //using the unique icon index provided by windows save us from duplicate keys - key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon); - } - pixmap = qt_pixmapFromWinHICON(info.hIcon); + Q_FOREACH (int size, sizes) { + QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size)); if (!pixmap.isNull()) { retIcon.addPixmap(pixmap); - if (!key.isEmpty()) - QPixmapCache::insert(key + QLatin1Char('l'), pixmap); - } - else { - qWarning("QFileIconProviderPrivate::getWinIcon() no large icon found"); + if (cacheable) + QPixmapCache::insert(keyBase + QString::number(size), pixmap); } - DestroyIcon(info.hIcon); } - return retIcon; -} - -#elif defined(Q_WS_MAC) -QIcon QFileIconProviderPrivate::getMacIcon(const QFileInfo &fi) const -{ - QIcon retIcon; - QString fileExtension = fi.suffix().toUpper(); - fileExtension.prepend(QLatin1String(".")); - const QString keyBase = QLatin1String("qt_") + fileExtension; - - QPixmap pixmap; - if (fi.isFile() && !fi.isExecutable() && !fi.isSymLink()) { - QPixmapCache::find(keyBase + QLatin1String("16"), pixmap); - } - - if (!pixmap.isNull()) { - retIcon.addPixmap(pixmap); - if (QPixmapCache::find(keyBase + QLatin1String("32"), pixmap)) { - retIcon.addPixmap(pixmap); - if (QPixmapCache::find(keyBase + QLatin1String("64"), pixmap)) { - retIcon.addPixmap(pixmap); - if (QPixmapCache::find(keyBase + QLatin1String("128"), pixmap)) { - retIcon.addPixmap(pixmap); - return retIcon; - } - } - } - } - - - FSRef macRef; - OSStatus status = FSPathMakeRef(reinterpret_cast<const UInt8*>(fi.canonicalFilePath().toUtf8().constData()), - &macRef, 0); - if (status != noErr) - return retIcon; - FSCatalogInfo info; - HFSUniStr255 macName; - status = FSGetCatalogInfo(&macRef, kIconServicesCatalogInfoMask, &info, &macName, 0, 0); - if (status != noErr) - return retIcon; - IconRef iconRef; - SInt16 iconLabel; - status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode, - kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag, - &iconRef, &iconLabel); - if (status != noErr) - return retIcon; - qt_mac_constructQIconFromIconRef(iconRef, 0, &retIcon); - ReleaseIconRef(iconRef); - - if (fi.isFile() && !fi.isExecutable() && !fi.isSymLink()) { - pixmap = retIcon.pixmap(16); - QPixmapCache::insert(keyBase + QLatin1String("16"), pixmap); - pixmap = retIcon.pixmap(32); - QPixmapCache::insert(keyBase + QLatin1String("32"), pixmap); - pixmap = retIcon.pixmap(64); - QPixmapCache::insert(keyBase + QLatin1String("64"), pixmap); - pixmap = retIcon.pixmap(128); - QPixmapCache::insert(keyBase + QLatin1String("128"), pixmap); - } return retIcon; } -#endif /*! @@ -412,15 +286,10 @@ QIcon QFileIconProvider::icon(const QFileInfo &info) const } #endif -#ifdef Q_WS_MAC - QIcon retIcon = d->getMacIcon(info); + QIcon retIcon = d->getIcon(info); if (!retIcon.isNull()) return retIcon; -#elif defined Q_OS_WIN - QIcon icon = d->getWinIcon(info); - if (!icon.isNull()) - return icon; -#endif + if (info.isRoot()) #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) { @@ -445,6 +314,7 @@ QIcon QFileIconProvider::icon(const QFileInfo &info) const #else return d->getIcon(QStyle::SP_DriveHDIcon); #endif + if (info.isFile()) { if (info.isSymLink()) return d->getIcon(QStyle::SP_FileLinkIcon); diff --git a/src/widgets/itemviews/qitemeditorfactory.cpp b/src/widgets/itemviews/qitemeditorfactory.cpp index 5162a5534c..5f24c3ea1b 100644 --- a/src/widgets/itemviews/qitemeditorfactory.cpp +++ b/src/widgets/itemviews/qitemeditorfactory.cpp @@ -73,6 +73,36 @@ public: #endif // QT_NO_COMBOBOX + +#ifndef QT_NO_SPINBOX + +class QUIntSpinBox : public QSpinBox +{ + Q_OBJECT + Q_PROPERTY(uint value READ uintValue WRITE setUIntValue NOTIFY uintValueChanged USER true) +public: + explicit QUIntSpinBox(QWidget *parent = 0) + : QSpinBox(parent) + { + connect(this, SIGNAL(valueChanged(int)), SIGNAL(uintValueChanged())); + } + + uint uintValue() + { + return value(); + } + + void setUIntValue(uint value_) + { + return setValue(value_); + } + +Q_SIGNALS: + void uintValueChanged(); +}; + +#endif // QT_NO_SPINBOX + /*! \class QItemEditorFactory \brief The QItemEditorFactory class provides widgets for editing item data @@ -206,8 +236,9 @@ QWidget *QDefaultItemEditorFactory::createEditor(int userType, QWidget *parent) #endif #ifndef QT_NO_SPINBOX case QVariant::UInt: { - QSpinBox *sb = new QSpinBox(parent); + QSpinBox *sb = new QUIntSpinBox(parent); sb->setFrame(false); + sb->setMinimum(0); sb->setMaximum(INT_MAX); return sb; } case QVariant::Int: { diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index ff703c9d8a..592354836a 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -3162,7 +3162,7 @@ void QListView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive()) { if (current.isValid()) { - int entry = visualIndex(current) + 1; + int entry = visualIndex(current); QAccessibleEvent event(this, QAccessible::Focus); event.setChild(entry); QAccessible::updateAccessibility(&event); @@ -3183,14 +3183,14 @@ void QListView::selectionChanged(const QItemSelection &selected, // ### does not work properly for selection ranges. QModelIndex sel = selected.indexes().value(0); if (sel.isValid()) { - int entry = visualIndex(sel) + 1; + int entry = visualIndex(sel); QAccessibleEvent event(this, QAccessible::Selection); event.setChild(entry); QAccessible::updateAccessibility(&event); } QModelIndex desel = deselected.indexes().value(0); if (desel.isValid()) { - int entry = visualIndex(desel) + 1; + int entry = visualIndex(desel); QAccessibleEvent event(this, QAccessible::SelectionRemove); event.setChild(entry); QAccessible::updateAccessibility(&event); diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp index d05efaa5b0..d16c999508 100644 --- a/src/widgets/kernel/qboxlayout.cpp +++ b/src/widgets/kernel/qboxlayout.cpp @@ -162,7 +162,7 @@ void QBoxLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *b int t = topMargin; int r = rightMargin; int b = bottomMargin; -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC Q_Q(const QBoxLayout); if (horz(dir)) { QBoxLayoutItem *leftBox = 0; @@ -311,7 +311,7 @@ void QBoxLayoutPrivate::setupGeom() if (!empty) { if (fixedSpacing >= 0) { spacing = (previousNonEmptyIndex >= 0) ? fixedSpacing : 0; -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC if (!horz(dir) && previousNonEmptyIndex >= 0) { QBoxLayoutItem *sibling = (dir == QBoxLayout::TopToBottom ? box : list.at(previousNonEmptyIndex)); if (sibling) { diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp index 5dd840e80a..b5cd746c03 100644 --- a/src/widgets/kernel/qgridlayout.cpp +++ b/src/widgets/kernel/qgridlayout.cpp @@ -231,7 +231,7 @@ void QGridLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int * int t = topMargin; int r = rightMargin; int b = bottomMargin; -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC int leftMost = INT_MAX; int topMost = INT_MAX; int rightMost = 0; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 29083b0670..bb148a52ac 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -8318,10 +8318,11 @@ void QWidget::changeEvent(QEvent * event) } break; -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC case QEvent::MacSizeChange: updateGeometry(); break; +#elif defined Q_WS_MAC case QEvent::ToolTipChange: case QEvent::MouseTrackingChange: qt_mac_update_mouseTracking(this); @@ -9923,6 +9924,24 @@ static void setAttribute_internal(Qt::WidgetAttribute attribute, bool on, QWidge } } +#ifdef Q_OS_MAC +void QWidgetPrivate::macUpdateSizeAttribute() +{ + Q_Q(QWidget); + QEvent event(QEvent::MacSizeChange); + QApplication::sendEvent(q, &event); + for (int i = 0; i < children.size(); ++i) { + QWidget *w = qobject_cast<QWidget *>(children.at(i)); + if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) + && !q->testAttribute(Qt::WA_MacMiniSize) // no attribute set? inherit from parent + && !w->testAttribute(Qt::WA_MacSmallSize) + && !w->testAttribute(Qt::WA_MacNormalSize)) + w->d_func()->macUpdateSizeAttribute(); + } + resolveFont(); +} +#endif + /*! Sets the attribute \a attribute on this widget if \a on is true; otherwise clears the attribute. @@ -10004,7 +10023,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) case Qt::WA_MacNormalSize: case Qt::WA_MacSmallSize: case Qt::WA_MacMiniSize: -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC { // We can only have one of these set at a time const Qt::WidgetAttribute MacSizes[] = { Qt::WA_MacNormalSize, Qt::WA_MacSmallSize, diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index eb67f756e8..8aba276966 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -725,7 +725,9 @@ public: void grabMouseWhileInWindow(); void registerTouchWindow(); void winSetupGestures(); -#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC +#elif defined(Q_OS_MAC) // <--------------------------------------------------------- MAC + void macUpdateSizeAttribute(); +#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC (old stuff) // This is new stuff uint needWindowChange : 1; @@ -752,7 +754,6 @@ public: //these are here just for code compat (HIViews) Qt::HANDLE qd_hd; - void macUpdateSizeAttribute(); void macUpdateHideOnSuspend(); void macUpdateOpaqueSizeGrip(); void macUpdateIgnoreMouseEvents(); @@ -802,8 +803,6 @@ public: static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); void registerTouchWindow(bool enable = true); #endif - void setMaxWindowState_helper(); - void setFullScreenSize_helper(); bool stealKeyboardGrab(bool grab); bool stealMouseGrab(bool grab); }; diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 86d8da254a..2950c19768 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -547,6 +547,9 @@ void QWidgetPrivate::show_sys() } } +#ifndef QT_NO_CURSOR + qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show +#endif invalidateBuffer(q->rect()); window->setVisible(true); } @@ -583,33 +586,6 @@ void QWidgetPrivate::hide_sys() window->setVisible(false); } -void QWidgetPrivate::setMaxWindowState_helper() -{ - Q_Q(QWidget); - - const uint old_state = data.in_set_window_state; - data.in_set_window_state = 1; - - const QRect desktop = qApp->desktop()->availableGeometry(qApp->desktop()->screenNumber(q)); - q->setGeometry(desktop); - - data.in_set_window_state = old_state; -} - -void QWidgetPrivate::setFullScreenSize_helper() -{ - Q_Q(QWidget); - - const uint old_state = data.in_set_window_state; - data.in_set_window_state = 1; - - const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q)); - q->move(screen.topLeft()); - q->resize(screen.size()); - - data.in_set_window_state = old_state; -} - Qt::WindowState effectiveState(Qt::WindowStates state) { if (state & Qt::WindowMinimized) @@ -632,7 +608,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate) data->window_state = newstate; data->in_set_window_state = 1; - bool needShow = false; Qt::WindowState newEffectiveState = effectiveState(newstate); Qt::WindowState oldEffectiveState = effectiveState(oldstate); if (isWindow() && newEffectiveState != oldEffectiveState) { @@ -646,54 +621,9 @@ void QWidget::setWindowState(Qt::WindowStates newstate) Q_ASSERT(windowHandle()); windowHandle()->setWindowState(newEffectiveState); - bool supported = windowHandle()->windowState() == newEffectiveState; - - if (!supported) { - const bool wasResized = testAttribute(Qt::WA_Resized); - const bool wasMoved = testAttribute(Qt::WA_Moved); - - // undo the effects of the old emulated state - if (oldEffectiveState == Qt::WindowFullScreen) { - setParent(0, d->topData()->savedFlags); - needShow = true; - } else if (oldEffectiveState == Qt::WindowMinimized) { - needShow = true; - } - - // emulate the new window state - if (newEffectiveState == Qt::WindowMinimized) { - //### not ideal... - hide(); - needShow = false; - } else if (newEffectiveState == Qt::WindowFullScreen) { - d->topData()->savedFlags = windowFlags(); - setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint)); - d->setFullScreenSize_helper(); - raise(); - needShow = true; - } else if (newEffectiveState == Qt::WindowMaximized) { - createWinId(); - d->setMaxWindowState_helper(); - } else if (newEffectiveState == Qt::WindowNoState) { - // reset old geometry - QRect r = d->topData()->normalGeometry; - if (r.width() >= 0) { - d->topData()->normalGeometry = QRect(0,0,-1,-1); - setGeometry(r); - } - } - - // setWindowState() is not an explicit move/resize, same as the supported == true - // case - setAttribute(Qt::WA_Resized, wasResized); - setAttribute(Qt::WA_Moved, wasMoved); - } } data->in_set_window_state = 0; - if (needShow) - setVisible(true); - if (newstate & Qt::WindowActive) activateWindow(); diff --git a/src/widgets/styles/images/fusion_arrow.png b/src/widgets/styles/images/fusion_arrow.png Binary files differnew file mode 100644 index 0000000000..d7945e7f76 --- /dev/null +++ b/src/widgets/styles/images/fusion_arrow.png diff --git a/src/widgets/styles/images/fusion_groupbox.png b/src/widgets/styles/images/fusion_groupbox.png Binary files differnew file mode 100644 index 0000000000..98585ee8c7 --- /dev/null +++ b/src/widgets/styles/images/fusion_groupbox.png diff --git a/src/widgets/styles/qcleanlooksstyle.cpp b/src/widgets/styles/qcleanlooksstyle.cpp index 99e4b179f4..5b8b5e0b9f 100644 --- a/src/widgets/styles/qcleanlooksstyle.cpp +++ b/src/widgets/styles/qcleanlooksstyle.cpp @@ -67,6 +67,7 @@ #include <qwizard.h> #include <qlibrary.h> #include <private/qstylehelper_p.h> +#include <private/qstyleanimation_p.h> QT_BEGIN_NAMESPACE @@ -1750,18 +1751,21 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o reverse = !reverse; QRect progressBar; + Q_D(const QCleanlooksStyle); if (!indeterminate) { if (!reverse) { progressBar.setRect(rect.left() + 1, rect.top() + 1, width + 1, rect.height() - 3); } else { progressBar.setRect(rect.right() - 1 - width, rect.top() + 1, width + 1, rect.height() - 3); } + d->stopAnimation(option->styleObject); } else { - Q_D(const QCleanlooksStyle); int slideWidth = ((rect.width() - 4) * 2) / 3; - int step = ((d->animateStep * slideWidth) / d->animationFps) % slideWidth; - if ((((d->animateStep * slideWidth) / d->animationFps) % (2 * slideWidth)) >= slideWidth) - step = slideWidth - step; + int step = 0; + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(option->styleObject))) + step = animation->progressStep(slideWidth); + else + d->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject)); progressBar.setRect(rect.left() + 1 + step, rect.top() + 1, slideWidth / 2, rect.height() - 3); } diff --git a/src/widgets/styles/qcleanlooksstyle_p.h b/src/widgets/styles/qcleanlooksstyle_p.h index ccf0d5e1c2..5a6bef5fe7 100644 --- a/src/widgets/styles/qcleanlooksstyle_p.h +++ b/src/widgets/styles/qcleanlooksstyle_p.h @@ -66,7 +66,6 @@ class QCleanlooksStylePrivate : public QWindowsStylePrivate public: QCleanlooksStylePrivate() : QWindowsStylePrivate() { - animationFps = 24; } ~QCleanlooksStylePrivate() { diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 5c34caef6b..4dd92c1a0c 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -75,6 +75,7 @@ #include <qsettings.h> #include <qvariant.h> #include <qpixmapcache.h> +#include <private/qstyleanimation_p.h> #include <limits.h> @@ -173,7 +174,10 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q if (opt->state & (State_Sunken | State_On)) { ir.adjust(2, 2, -2, -2); p->setBrush(opt->palette.foreground()); + bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting); + p->setRenderHint(QPainter::Qt4CompatiblePainting); p->drawEllipse(ir); + p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting); } break; } case PE_FrameFocusRect: @@ -276,35 +280,38 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q break; #endif // QT_NO_PROGRESSBAR case PE_IndicatorBranch: { + static const int decoration_size = 9; int mid_h = opt->rect.x() + opt->rect.width() / 2; int mid_v = opt->rect.y() + opt->rect.height() / 2; int bef_h = mid_h; int bef_v = mid_v; int aft_h = mid_h; int aft_v = mid_v; -#ifndef QT_NO_IMAGEFORMAT_XPM - static const int decoration_size = 9; - static QPixmap open(tree_branch_open_xpm); - static QPixmap closed(tree_branch_closed_xpm); if (opt->state & State_Children) { int delta = decoration_size / 2; bef_h -= delta; bef_v -= delta; aft_h += delta; aft_v += delta; - p->drawPixmap(bef_h, bef_v, opt->state & State_Open ? open : closed); + p->drawLine(bef_h + 2, bef_v + 4, bef_h + 6, bef_v + 4); + if (!(opt->state & State_Open)) + p->drawLine(bef_h + 4, bef_v + 2, bef_h + 4, bef_v + 6); + QPen oldPen = p->pen(); + p->setPen(opt->palette.dark().color()); + p->drawRect(bef_h, bef_v, decoration_size - 1, decoration_size - 1); + p->setPen(oldPen); } -#endif // QT_NO_IMAGEFORMAT_XPM + QBrush brush(opt->palette.dark().color(), Qt::Dense4Pattern); if (opt->state & State_Item) { if (opt->direction == Qt::RightToLeft) - p->drawLine(opt->rect.left(), mid_v, bef_h, mid_v); + p->fillRect(opt->rect.left(), mid_v, bef_h - opt->rect.left(), 1, brush); else - p->drawLine(aft_h, mid_v, opt->rect.right(), mid_v); + p->fillRect(aft_h, mid_v, opt->rect.right() - aft_h + 1, 1, brush); } if (opt->state & State_Sibling) - p->drawLine(mid_h, aft_v, mid_h, opt->rect.bottom()); + p->fillRect(mid_h, aft_v, 1, opt->rect.bottom() - aft_v + 1, brush); if (opt->state & (State_Open | State_Children | State_Item | State_Sibling)) - p->drawLine(mid_h, opt->rect.y(), mid_h, bef_v); + p->fillRect(mid_h, opt->rect.y(), 1, bef_v - opt->rect.y(), brush); break; } case PE_FrameStatusBarItem: qDrawShadeRect(p, opt->rect, opt->palette, true, 1, 0, 0); @@ -526,6 +533,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q p->translate(sx + bsx, sy + bsy); p->setPen(opt->palette.buttonText().color()); p->setBrush(opt->palette.buttonText()); + p->setRenderHint(QPainter::Qt4CompatiblePainting); p->drawPolygon(a); p->restore(); break; } @@ -1048,6 +1056,51 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget } #endif //QT_NO_TABBAR +/*! \internal */ +QList<const QObject*> QCommonStylePrivate::animationTargets() const +{ + return animations.keys(); +} + +/*! \internal */ +QStyleAnimation * QCommonStylePrivate::animation(const QObject *target) const +{ + return animations.value(target); +} + +/*! \internal */ +void QCommonStylePrivate::startAnimation(QStyleAnimation *animation) const +{ + Q_Q(const QCommonStyle); + stopAnimation(animation->target()); + q->connect(animation, SIGNAL(finished()), SLOT(_q_removeAnimation()), Qt::UniqueConnection); + q->connect(animation, SIGNAL(destroyed()), SLOT(_q_removeAnimation()), Qt::UniqueConnection); + animations.insert(animation->target(), animation); + animation->start(); +} + +/*! \internal */ +void QCommonStylePrivate::stopAnimation(const QObject *target) const +{ + QStyleAnimation *animation = animations.value(target); + if (animation) { + if (animation->state() == QAbstractAnimation::Stopped) + animations.take(target)->deleteLater(); + else + animation->stop(); + } +} + +/*! \internal */ +void QCommonStylePrivate::_q_removeAnimation() +{ + Q_Q(QCommonStyle); + QObject *animation = q->sender(); + if (animation) { + animations.remove(animation->parent()); + animation->deleteLater(); + } +} /*! \reimp @@ -1530,7 +1583,10 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, } p->setPen(tb->palette.mid().color().darker(150)); + bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting); + p->setRenderHint(QPainter::Qt4CompatiblePainting); p->drawPolygon(a); + p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting); p->setPen(tb->palette.light().color()); if (tb->direction != Qt::RightToLeft) { p->drawLine(0, 2, tb->rect.width() - d, 2); @@ -3438,6 +3494,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl p->setPen(Qt::NoPen); p->setBrush(pal.button()); + p->setRenderHint(QPainter::Qt4CompatiblePainting); p->drawPolygon(arrow); a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]); @@ -5467,67 +5524,24 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption break; } } // if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) - if (!icon.isNull()) - return icon; -#if defined(Q_WS_MAC) + + if (!icon.isNull()) + return icon; + +#if defined(Q_OS_MAC) if (QApplication::desktopSettingsAware()) { - OSType iconType = 0; switch (standardIcon) { - case QStyle::SP_MessageBoxQuestion: - iconType = kQuestionMarkIcon; - break; - case QStyle::SP_MessageBoxInformation: - iconType = kAlertNoteIcon; - break; - case QStyle::SP_MessageBoxWarning: - iconType = kAlertCautionIcon; - break; - case QStyle::SP_MessageBoxCritical: - iconType = kAlertStopIcon; - break; - case SP_DesktopIcon: - iconType = kDesktopIcon; - break; - case SP_TrashIcon: - iconType = kTrashIcon; - break; - case SP_ComputerIcon: - iconType = kComputerIcon; - break; - case SP_DriveFDIcon: - iconType = kGenericFloppyIcon; - break; - case SP_DriveHDIcon: - iconType = kGenericHardDiskIcon; - break; - case SP_DriveCDIcon: - case SP_DriveDVDIcon: - iconType = kGenericCDROMIcon; - break; - case SP_DriveNetIcon: - iconType = kGenericNetworkIcon; - break; - case SP_DirOpenIcon: - iconType = kOpenFolderIcon; - break; - case SP_DirClosedIcon: - case SP_DirLinkIcon: - iconType = kGenericFolderIcon; - break; - case SP_FileLinkIcon: - case SP_FileIcon: - iconType = kGenericDocumentIcon; - break; case SP_DirIcon: { // A rather special case - QIcon closeIcon = QStyle::standardIcon(SP_DirClosedIcon, option, widget); - QIcon openIcon = QStyle::standardIcon(SP_DirOpenIcon, option, widget); + QIcon closeIcon = QCommonStyle::standardIcon(SP_DirClosedIcon, option, widget); + QIcon openIcon = QCommonStyle::standardIcon(SP_DirOpenIcon, option, widget); closeIcon.addPixmap(openIcon.pixmap(16, 16), QIcon::Normal, QIcon::On); closeIcon.addPixmap(openIcon.pixmap(32, 32), QIcon::Normal, QIcon::On); closeIcon.addPixmap(openIcon.pixmap(64, 64), QIcon::Normal, QIcon::On); closeIcon.addPixmap(openIcon.pixmap(128, 128), QIcon::Normal, QIcon::On); return closeIcon; } + case SP_TitleBarNormalButton: case SP_TitleBarCloseButton: { QIcon titleBarIcon; @@ -5540,35 +5554,49 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption } return titleBarIcon; } - default: - break; - } - if (iconType != 0) { - QIcon retIcon; - IconRef icon; - IconRef overlayIcon = 0; - if (iconType != kGenericApplicationIcon) { - GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon); - } else { - FSRef fsRef; - ProcessSerialNumber psn = { 0, kCurrentProcess }; - GetProcessBundleLocation(&psn, &fsRef); - GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0); - if (standardIcon == SP_MessageBoxCritical) { - overlayIcon = icon; - GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon); + + case SP_MessageBoxQuestion: + case SP_MessageBoxInformation: + case SP_MessageBoxWarning: + case SP_MessageBoxCritical: + case SP_DesktopIcon: + case SP_TrashIcon: + case SP_ComputerIcon: + case SP_DriveFDIcon: + case SP_DriveHDIcon: + case SP_DriveCDIcon: + case SP_DriveDVDIcon: + case SP_DriveNetIcon: + case SP_DirOpenIcon: + case SP_DirClosedIcon: + case SP_DirLinkIcon: + case SP_FileLinkIcon: + case SP_FileIcon: + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon); + QIcon retIcon; + QList<int> sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value<QList<int> >(); + Q_FOREACH (int size, sizes) { + QPixmap mainIcon; + const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size); + if (standardIcon >= QStyle::SP_CustomBase) { + mainIcon = theme->standardPixmap(sp, QSizeF(size, size)); + } else if (QPixmapCache::find(cacheKey, mainIcon) == false) { + mainIcon = theme->standardPixmap(sp, QSizeF(size, size)); + QPixmapCache::insert(cacheKey, mainIcon); + } + + retIcon.addPixmap(mainIcon); } + if (!retIcon.isNull()) + return retIcon; } - if (icon) { - qt_mac_constructQIconFromIconRef(icon, overlayIcon, &retIcon, standardIcon); - ReleaseIconRef(icon); - } - if (overlayIcon) - ReleaseIconRef(overlayIcon); - return retIcon; + + default: + break; } } // if (QApplication::desktopSettingsAware()) -#endif // Q_WS_MAC +#endif // Q_OS_MAC switch (standardIcon) { #ifndef QT_NO_IMAGEFORMAT_PNG @@ -5903,3 +5931,5 @@ void QCommonStyle::unpolish(QApplication *application) QT_END_NAMESPACE + +#include "moc_qcommonstyle.cpp" diff --git a/src/widgets/styles/qcommonstyle.h b/src/widgets/styles/qcommonstyle.h index ba0837a5d5..878213702c 100644 --- a/src/widgets/styles/qcommonstyle.h +++ b/src/widgets/styles/qcommonstyle.h @@ -100,6 +100,7 @@ protected: private: Q_DECLARE_PRIVATE(QCommonStyle) Q_DISABLE_COPY(QCommonStyle) + Q_PRIVATE_SLOT(d_func(), void _q_removeAnimation()) }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h index 496723f8dd..8f22dc7b79 100644 --- a/src/widgets/styles/qcommonstyle_p.h +++ b/src/widgets/styles/qcommonstyle_p.h @@ -44,6 +44,7 @@ #include "qcommonstyle.h" #include "qstyle_p.h" +#include "qstyleanimation_p.h" #include "qstyleoption.h" @@ -67,17 +68,22 @@ class QCommonStylePrivate : public QStylePrivate { Q_DECLARE_PUBLIC(QCommonStyle) public: - inline QCommonStylePrivate() + inline QCommonStylePrivate() : #ifndef QT_NO_ITEMVIEWS - : cachedOption(0) + cachedOption(0), #endif + animationFps(30) { } -#ifndef QT_NO_ITEMVIEWS ~QCommonStylePrivate() { + qDeleteAll(animations); +#ifndef QT_NO_ITEMVIEWS delete cachedOption; +#endif } + +#ifndef QT_NO_ITEMVIEWS void viewItemDrawText(QPainter *p, const QStyleOptionViewItem *option, const QRect &rect) const; void viewItemLayout(const QStyleOptionViewItem *opt, QRect *checkRect, QRect *pixmapRect, QRect *textRect, bool sizehint) const; @@ -106,6 +112,17 @@ public: #ifndef QT_NO_TABBAR void tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const; #endif + + int animationFps; + void _q_removeAnimation(); + + QList<const QObject*> animationTargets() const; + QStyleAnimation* animation(const QObject *target) const; + void startAnimation(QStyleAnimation *animation) const; + void stopAnimation(const QObject *target) const; + +private: + mutable QHash<const QObject*, QStyleAnimation*> animations; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qcommonstylepixmaps_p.h b/src/widgets/styles/qcommonstylepixmaps_p.h index 4dcbe86ada..5e63302f35 100644 --- a/src/widgets/styles/qcommonstylepixmaps_p.h +++ b/src/widgets/styles/qcommonstylepixmaps_p.h @@ -75,33 +75,6 @@ static const char * const check_list_controller_xpm[] = { " ", " "}; -static const char * const tree_branch_open_xpm[] = { -"9 9 2 1", -" c None", -"# c #000000", -"#########", -"# #", -"# ##### #", -"# ### #", -"# ### #", -"# # #", -"# # #", -"# #", -"#########"}; - -static const char * const tree_branch_closed_xpm[] = { -"9 9 2 1", -" c None", -"# c #000000", -"#########", -"# #", -"# # #", -"# ### #", -"# ##### #", -"# ### #", -"# # #", -"# #", -"#########"}; static const char * const tb_extension_arrow_v_xpm[] = { "5 8 3 1", diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp new file mode 100644 index 0000000000..603369d117 --- /dev/null +++ b/src/widgets/styles/qfusionstyle.cpp @@ -0,0 +1,3578 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qfusionstyle.h" +#include "qfusionstyle_p.h" + +#if !defined(QT_NO_STYLE_FUSION) || defined(QT_PLUGIN) +#include "qcommonstyle_p.h" +#include <qcombobox.h> +#include <qpushbutton.h> +#include <qpainter.h> +#include <qdir.h> +#include <qhash.h> +#include <qstyleoption.h> +#include <qapplication.h> +#include <qmainwindow.h> +#include <qfont.h> +#include <qgroupbox.h> +#include <qprocess.h> +#include <qpixmapcache.h> +#include <qdialogbuttonbox.h> +#include <qscrollbar.h> +#include <qspinbox.h> +#include <qslider.h> +#include <qsplitter.h> +#include <qprogressbar.h> +#include <qwizard.h> +#include <qlibrary.h> +#include <qdrawutil.h> +#include <private/qstylehelper_p.h> +#include <private/qdrawhelper_p.h> +#include <private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +using namespace QStyleHelper; + +enum Direction { + TopDown, + FromLeft, + BottomUp, + FromRight +}; + +// from windows style +static const int windowsItemFrame = 2; // menu item frame width +static const int windowsItemHMargin = 3; // menu item hor text margin +static const int windowsItemVMargin = 8; // menu item ver text margin +static const int windowsRightBorder = 15; // right border on windows + +static const int groupBoxBottomMargin = 0; // space below the groupbox +static const int groupBoxTitleMargin = 2; // space between contents and title +static const int groupBoxTopMargin = 18; + + +/* XPM */ +static const char * const dock_widget_close_xpm[] = { + "11 13 7 1", + " c None", + ". c #D5CFCB", + "+ c #8F8B88", + "@ c #6C6A67", + "# c #ABA6A3", + "$ c #B5B0AC", + "% c #A4A09D", + " ", + " +@@@@@@@+ ", + "+# #+", + "@ $@ @$ @", + "@ @@@ @@@ @", + "@ @@@@@ @", + "@ @@@ @", + "@ @@@@@ @", + "@ @@@ @@@ @", + "@ $@ @$ @", + "+% #+", + " +@@@@@@@+ ", + " "}; + +static const char * const dock_widget_restore_xpm[] = { + "11 13 7 1", + " c None", + ". c #D5CFCB", + "+ c #8F8B88", + "@ c #6C6A67", + "# c #ABA6A3", + "$ c #B5B0AC", + "% c #A4A09D", + " ", + " +@@@@@@@+ ", + "+# #+", + "@ #@@@# @", + "@ @ @ @", + "@ #@@@# @ @", + "@ @ @ @ @", + "@ @ @@@ @", + "@ @ @ @", + "@ #@@@# @", + "+% #+", + " +@@@@@@@+ ", + " "}; + +static const char * const workspace_minimize[] = { + "11 13 7 1", + " c None", + ". c #D5CFCB", + "+ c #8F8B88", + "@ c #6C6A67", + "# c #ABA6A3", + "$ c #B5B0AC", + "% c #A4A09D", + " ", + " +@@@@@@@+ ", + "+# #+", + "@ @", + "@ @", + "@ @", + "@ @@@@@@@ @", + "@ @@@@@@@ @", + "@ @", + "@ @", + "+% #+", + " +@@@@@@@+ ", + " "}; + + +static const char * const qt_titlebar_context_help[] = { + "10 10 3 1", + " c None", + "# c #000000", + "+ c #444444", + " +####+ ", + " ### ### ", + " ## ## ", + " +##+ ", + " +## ", + " ## ", + " ## ", + " ", + " ## ", + " ## "}; + + +static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50) +{ + const int maxFactor = 100; + QColor tmp = colorA; + tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor); + tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor); + tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor); + return tmp; +} + +static QPixmap colorizedImage(const QString &fileName, const QColor &color, int rotation = 0) { + + QString pixmapName = QLatin1String("$qt_ia-") % fileName % HexString<uint>(color.rgba()) % QString::number(rotation); + QPixmap pixmap; + if (!QPixmapCache::find(pixmapName, pixmap)) { + QImage image(fileName); + + if (image.format() != QImage::Format_ARGB32_Premultiplied) + image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied); + + int width = image.width(); + int height = image.height(); + int source = color.rgba(); + + unsigned char sourceRed = qRed(source); + unsigned char sourceGreen = qGreen(source); + unsigned char sourceBlue = qBlue(source); + + for (int y = 0; y < height; ++y) + { + QRgb *data = (QRgb*) image.scanLine(y); + for (int x = 0 ; x < width ; x++) { + QRgb col = data[x]; + unsigned int colorDiff = (qBlue(col) - qRed(col)); + unsigned char gray = qGreen(col); + unsigned char red = gray + qt_div_255(sourceRed * colorDiff); + unsigned char green = gray + qt_div_255(sourceGreen * colorDiff); + unsigned char blue = gray + qt_div_255(sourceBlue * colorDiff); + unsigned char alpha = qt_div_255(qAlpha(col) * qAlpha(source)); + data[x] = qRgba(red, green, blue, alpha); + } + } + if (rotation != 0) { + QTransform transform; + transform.translate(-image.width()/2, -image.height()/2); + transform.rotate(rotation); + transform.translate(image.width()/2, image.height()/2); + image = image.transformed(transform); + } + + pixmap = QPixmap::fromImage(image); + QPixmapCache::insert(pixmapName, pixmap); + } + return pixmap; +} + +// The default button and handle gradient +static QLinearGradient qt_fusion_gradient(const QRect &rect, const QBrush &baseColor, Direction direction = TopDown) +{ + int x = rect.center().x(); + int y = rect.center().y(); + QLinearGradient gradient; + switch (direction) { + case FromLeft: + gradient = QLinearGradient(rect.left(), y, rect.right(), y); + break; + case FromRight: + gradient = QLinearGradient(rect.right(), y, rect.left(), y); + break; + case BottomUp: + gradient = QLinearGradient(x, rect.bottom(), x, rect.top()); + break; + case TopDown: + default: + gradient = QLinearGradient(x, rect.top(), x, rect.bottom()); + break; + } + if (baseColor.gradient()) + gradient.setStops(baseColor.gradient()->stops()); + else { + QColor gradientStartColor = baseColor.color().lighter(124); + QColor gradientStopColor = baseColor.color().lighter(102); + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(1, gradientStopColor); + // Uncomment for adding shiny shading + // QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 55); + // QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 45); + // gradient.setColorAt(0.5, midColor1); + // gradient.setColorAt(0.501, midColor2); + } + return gradient; +} + + +static void qt_fusion_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken) +{ + QColor dark; + dark.setHsv(option->palette.button().color().hue(), + qMin(255, (int)(option->palette.button().color().saturation())), + qMin(255, (int)(option->palette.button().color().value()*0.7))); + + QColor highlight = option->palette.highlight().color(); + + bool active = (option->titleBarState & QStyle::State_Active); + QColor titleBarHighlight(255, 255, 255, 60); + + if (sunken) + painter->fillRect(tmp.adjusted(1, 1, -1, -1), option->palette.highlight().color().darker(120)); + else if (hover) + painter->fillRect(tmp.adjusted(1, 1, -1, -1), QColor(255, 255, 255, 20)); + + QColor mdiButtonGradientStartColor; + QColor mdiButtonGradientStopColor; + + mdiButtonGradientStartColor = QColor(0, 0, 0, 40); + mdiButtonGradientStopColor = QColor(255, 255, 255, 60); + + if (sunken) + titleBarHighlight = highlight.darker(130); + + QLinearGradient gradient(tmp.center().x(), tmp.top(), tmp.center().x(), tmp.bottom()); + gradient.setColorAt(0, mdiButtonGradientStartColor); + gradient.setColorAt(1, mdiButtonGradientStopColor); + QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(180): dark.darker(110)); + + painter->setPen(QPen(mdiButtonBorderColor, 1)); + const QLine lines[4] = { + QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()), + QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()), + QLine(tmp.left(), tmp.top() + 2, tmp.left(), tmp.bottom() - 2), + QLine(tmp.right(), tmp.top() + 2, tmp.right(), tmp.bottom() - 2) + }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + QPoint(tmp.left() + 1, tmp.top() + 1), + QPoint(tmp.right() - 1, tmp.top() + 1), + QPoint(tmp.left() + 1, tmp.bottom() - 1), + QPoint(tmp.right() - 1, tmp.bottom() - 1) + }; + painter->drawPoints(points, 4); + + painter->setPen(titleBarHighlight); + painter->drawLine(tmp.left() + 2, tmp.top() + 1, tmp.right() - 2, tmp.top() + 1); + painter->drawLine(tmp.left() + 1, tmp.top() + 2, tmp.left() + 1, tmp.bottom() - 2); + + painter->setPen(QPen(gradient, 1)); + painter->drawLine(tmp.right() + 1, tmp.top() + 2, tmp.right() + 1, tmp.bottom() - 2); + painter->drawPoint(tmp.right() , tmp.top() + 1); + + painter->drawLine(tmp.left() + 2, tmp.bottom() + 1, tmp.right() - 2, tmp.bottom() + 1); + painter->drawPoint(tmp.left() + 1, tmp.bottom()); + painter->drawPoint(tmp.right() - 1, tmp.bottom()); + painter->drawPoint(tmp.right() , tmp.bottom() - 1); +} + +/* + \internal +*/ +QFusionStylePrivate::QFusionStylePrivate() +{ + animationFps = 60; +} + +/*! + \class QFusionStyle + \brief The QFusionStyle class provides a custom widget style + + \inmodule QtWidgets + + The Fusion style provides a custom look and feel that is not + tied to a particular platform. + //{Fusion Style Widget Gallery} + \sa QWindowsXPStyle, QMacStyle, QCommonStyle, QPlastiqueStyle +*/ + +/*! + Constructs a QFusionStyle object. +*/ +QFusionStyle::QFusionStyle() : QCommonStyle(*new QFusionStylePrivate) +{ + setObjectName(QLatin1String("Fusion")); +} + +/*! + \internal + + Constructs a QFusionStyle object. +*/ +QFusionStyle::QFusionStyle(QFusionStylePrivate &dd) : QCommonStyle(dd) +{ +} + +/*! + Destroys the QFusionStyle object. +*/ +QFusionStyle::~QFusionStyle() +{ +} + +/*! + \fn void QFusionStyle::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, + bool enabled, const QString& text, QPalette::ColorRole textRole) const + + Draws the given \a text in the specified \a rectangle using the + provided \a painter and \a palette. + + Text is drawn using the painter's pen. If an explicit \a textRole + is specified, then the text is drawn using the \a palette's color + for the specified role. The \a enabled value indicates whether or + not the item is enabled; when reimplementing, this value should + influence how the item is drawn. + + The text is aligned and wrapped according to the specified \a + alignment. + + \sa Qt::Alignment +*/ +void QFusionStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, + bool enabled, const QString& text, QPalette::ColorRole textRole) const +{ + if (text.isEmpty()) + return; + + QPen savedPen = painter->pen(); + if (textRole != QPalette::NoRole) { + painter->setPen(QPen(pal.brush(textRole), savedPen.widthF())); + } + if (!enabled) { + QPen pen = painter->pen(); + painter->setPen(pen); + } + painter->drawText(rect, alignment, text); + painter->setPen(savedPen); +} + + +/*! + \reimp +*/ +void QFusionStyle::drawPrimitive(PrimitiveElement elem, + const QStyleOption *option, + QPainter *painter, const QWidget *widget) const +{ + Q_ASSERT(option); + Q_D (const QFusionStyle); + + QRect rect = option->rect; + int state = option->state; + + QColor outline = d->outline(option->palette); + QColor highlightedOutline = d->highlightedOutline(option->palette); + + QColor tabFrameColor = d->tabFrameColor(option->palette); + + switch (elem) { + + // No frame drawn + case PE_FrameGroupBox: + { + QPixmap pixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png")); + QRect frame = option->rect.adjusted(0, groupBoxTopMargin, 0, 0); + qDrawBorderPixmap(painter, frame, QMargins(6, 6, 6, 6), pixmap); + break; + } + case PE_IndicatorBranch: { + if (!(option->state & State_Children)) + break; + if (option->state & State_Open) + drawPrimitive(PE_IndicatorArrowDown, option, painter, widget); + else + drawPrimitive(PE_IndicatorArrowRight, option, painter, widget); + break; + } + case PE_FrameTabBarBase: + if (const QStyleOptionTabBarBase *tbb + = qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) { + painter->save(); + painter->setPen(QPen(outline.lighter(110), 0)); + switch (tbb->shape) { + case QTabBar::RoundedNorth: { + QRegion region(tbb->rect); + region -= tbb->selectedTabRect; + painter->drawLine(tbb->rect.topLeft(), tbb->rect.topRight()); + painter->setClipRegion(region); + painter->setPen(option->palette.light().color()); + painter->drawLine(tbb->rect.topLeft() + QPoint(0, 1), tbb->rect.topRight() + QPoint(0, 1)); + } + break; + case QTabBar::RoundedWest: + painter->drawLine(tbb->rect.left(), tbb->rect.top(), tbb->rect.left(), tbb->rect.bottom()); + break; + case QTabBar::RoundedSouth: + painter->drawLine(tbb->rect.left(), tbb->rect.bottom(), + tbb->rect.right(), tbb->rect.bottom()); + break; + case QTabBar::RoundedEast: + painter->drawLine(tbb->rect.topRight(), tbb->rect.bottomRight()); + break; + case QTabBar::TriangularNorth: + case QTabBar::TriangularEast: + case QTabBar::TriangularWest: + case QTabBar::TriangularSouth: + painter->restore(); + QCommonStyle::drawPrimitive(elem, option, painter, widget); + return; + } + painter->restore(); + } + return; + case PE_PanelScrollAreaCorner: { + painter->save(); + QColor alphaOutline = outline; + alphaOutline.setAlpha(180); + painter->setPen(alphaOutline); + painter->setBrush(option->palette.brush(QPalette::Window)); + painter->drawRect(option->rect); + painter->restore(); + } break; + case PE_IndicatorArrowUp: + case PE_IndicatorArrowDown: + case PE_IndicatorArrowRight: + case PE_IndicatorArrowLeft: + { + if (option->rect.width() <= 1 || option->rect.height() <= 1) + break; + QColor arrowColor = option->palette.foreground().color(); + QPixmap arrow; + int rotation = 0; + switch (elem) { + case PE_IndicatorArrowDown: + rotation = 180; + break; + case PE_IndicatorArrowRight: + rotation = 90; + break; + case PE_IndicatorArrowLeft: + rotation = -90; + break; + default: + break; + } + arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation); + QRect rect = option->rect; + QRect arrowRect; + int imageMax = qMin(arrow.height(), arrow.width()); + int rectMax = qMin(rect.height(), rect.width()); + int size = qMin(imageMax, rectMax); + + arrowRect.setWidth(size); + arrowRect.setHeight(size); + if (arrow.width() > arrow.height()) + arrowRect.setHeight(arrow.height() * size / arrow.width()); + else + arrowRect.setWidth(arrow.width() * size / arrow.height()); + + arrowRect.moveTopLeft(rect.center() - arrowRect.center()); + painter->save(); + painter->setRenderHint(QPainter::SmoothPixmapTransform); + painter->drawPixmap(arrowRect, arrow); + painter->restore(); + } + break; + case PE_IndicatorViewItemCheck: + { + QStyleOptionButton button; + button.QStyleOption::operator=(*option); + button.state &= ~State_MouseOver; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget); + } + return; + case PE_IndicatorHeaderArrow: + if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { + QRect r = header->rect; + QPixmap arrow; + QColor arrowColor = header->palette.foreground().color(); + QPoint offset = QPoint(0, -1); + + if (header->sortIndicator & QStyleOptionHeader::SortUp) { + arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor); + } else if (header->sortIndicator & QStyleOptionHeader::SortDown) { + arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180); + } if (!arrow.isNull()) { + r.setSize(QSize(arrow.width()/2, arrow.height()/2)); + r.moveCenter(header->rect.center()); + painter->drawPixmap(r.translated(offset), arrow); + } + } + break; + case PE_IndicatorButtonDropDown: + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + break; + + case PE_IndicatorToolBarSeparator: + { + QRect rect = option->rect; + const int margin = 6; + if (option->state & State_Horizontal) { + const int offset = rect.width()/2; + painter->setPen(QPen(option->palette.background().color().darker(110))); + painter->drawLine(rect.bottomLeft().x() + offset, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset, + rect.topLeft().y() + margin); + painter->setPen(QPen(option->palette.background().color().lighter(110))); + painter->drawLine(rect.bottomLeft().x() + offset + 1, + rect.bottomLeft().y() - margin, + rect.topLeft().x() + offset + 1, + rect.topLeft().y() + margin); + } else { //Draw vertical separator + const int offset = rect.height()/2; + painter->setPen(QPen(option->palette.background().color().darker(110))); + painter->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset, + rect.topRight().x() - margin, + rect.topRight().y() + offset); + painter->setPen(QPen(option->palette.background().color().lighter(110))); + painter->drawLine(rect.topLeft().x() + margin , + rect.topLeft().y() + offset + 1, + rect.topRight().x() - margin, + rect.topRight().y() + offset + 1); + } + } + break; + case PE_Frame: + if (widget && widget->inherits("QComboBoxPrivateContainer")){ + QStyleOption copy = *option; + copy.state |= State_Raised; + proxy()->drawPrimitive(PE_PanelMenu, ©, painter, widget); + break; + } + painter->save(); + painter->setPen(outline.lighter(108)); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->restore(); + break; + case PE_FrameMenu: + painter->save(); + { + painter->setPen(QPen(outline, 1)); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + QColor frameLight = option->palette.background().color().lighter(160); + QColor frameShadow = option->palette.background().color().darker(110); + + //paint beveleffect + QRect frame = option->rect.adjusted(1, 1, -1, -1); + painter->setPen(frameLight); + painter->drawLine(frame.topLeft(), frame.bottomLeft()); + painter->drawLine(frame.topLeft(), frame.topRight()); + + painter->setPen(frameShadow); + painter->drawLine(frame.topRight(), frame.bottomRight()); + painter->drawLine(frame.bottomLeft(), frame.bottomRight()); + } + painter->restore(); + break; + case PE_FrameDockWidget: + + painter->save(); + { + QColor softshadow = option->palette.background().color().darker(120); + + QRect rect= option->rect; + painter->setPen(softshadow); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->setPen(QPen(option->palette.light(), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1)); + painter->setPen(QPen(option->palette.background().color().darker(120), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1)); + painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1)); + + } + painter->restore(); + break; + case PE_PanelButtonTool: + painter->save(); + if ((option->state & State_Enabled || option->state & State_On) || !(option->state & State_AutoRaise)) { + if (widget && widget->inherits("QDockWidgetTitleButton")) { + if (option->state & State_MouseOver) + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + } else { + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + } + } + painter->restore(); + break; + case PE_IndicatorDockWidgetResizeHandle: + { + QStyleOption dockWidgetHandle = *option; + bool horizontal = option->state & State_Horizontal; + if (horizontal) + dockWidgetHandle.state &= ~State_Horizontal; + else + dockWidgetHandle.state |= State_Horizontal; + proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget); + } + break; + case PE_FrameWindow: + painter->save(); + { + QRect rect= option->rect; + painter->setPen(QPen(outline.darker(150), 0)); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->setPen(QPen(option->palette.light(), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), + QPoint(rect.left() + 1, rect.bottom() - 1)); + painter->setPen(QPen(option->palette.background().color().darker(120), 0)); + painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), + QPoint(rect.right() - 2, rect.bottom() - 1)); + painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), + QPoint(rect.right() - 1, rect.bottom() - 1)); + } + painter->restore(); + break; + case PE_FrameLineEdit: + { + QRect r = rect; + bool hasFocus = option->state & State_HasFocus; + + painter->save(); + + painter->setRenderHint(QPainter::Antialiasing, true); + // ### highdpi painter bug. + painter->translate(0.5, 0.5); + + // Draw Outline + painter->setPen( QPen(hasFocus ? highlightedOutline : outline, 0)); + painter->setBrush(option->palette.base()); + painter->drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2); + + if (hasFocus) { + QColor softHighlight = highlightedOutline; + softHighlight.setAlpha(40); + painter->setPen(softHighlight); + painter->drawRoundedRect(r.adjusted(1, 1, -2, -2), 1.7, 1.7); + } + // Draw inner shadow + painter->setPen(d->topShadow()); + painter->drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1)); + + painter->restore(); + + } + break; + case PE_IndicatorCheckBox: + painter->save(); + if (const QStyleOptionButton *checkbox = qstyleoption_cast<const QStyleOptionButton*>(option)) { + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + rect = rect.adjusted(0, 0, -1, -1); + + QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.foreground().color(), 85); + painter->setBrush(Qt::NoBrush); + + // Gradient fill + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + gradient.setColorAt(0, (state & State_Sunken) ? pressedColor : option->palette.base().color().darker(115)); + gradient.setColorAt(0.15, (state & State_Sunken) ? pressedColor : option->palette.base().color()); + gradient.setColorAt(1, (state & State_Sunken) ? pressedColor : option->palette.base().color()); + + painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient); + painter->setPen(QPen(outline.lighter(110), 1)); + + if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) + painter->setPen(QPen(highlightedOutline, 1)); + painter->drawRect(rect); + + if (checkbox->state & (State_On | State_Sunken | State_NoChange)) { + QColor checkMarkColor = option->palette.text().color().darker(120); + checkMarkColor.setAlpha(210); + painter->translate(-1, 0.5); + QPen checkPen = QPen(checkMarkColor, 1.8); + painter->setPen(checkPen); + painter->setBrush(Qt::NoBrush); + painter->translate(0.2, 0.0); + + // Draw checkmark + QPainterPath path; + path.moveTo(5, rect.height() / 2.0); + path.lineTo(rect.width() / 2.0 - 0, rect.height() - 3); + path.lineTo(rect.width() - 2.5, 3); + painter->drawPath(path.translated(rect.topLeft())); + + if (checkbox->state & State_NoChange) { + QColor bgc = option->palette.background().color(); + bgc.setAlpha(127); + painter->fillRect(rect.adjusted(1, 1, -1, -1), bgc); + } + + } + } + painter->restore(); + break; + case PE_IndicatorRadioButton: + painter->save(); + { + QColor pressedColor = mergedColors(option->palette.base().color(), option->palette.foreground().color(), 85); + painter->setBrush((state & State_Sunken) ? pressedColor : option->palette.base().color()); + painter->setRenderHint(QPainter::Antialiasing, true); + QPainterPath circle; + circle.addEllipse(rect.center() + QPoint(1.0, 1.0), 6.5, 6.5); + painter->setPen(QPen(option->palette.background().color().darker(150), 1)); + if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) + painter->setPen(QPen(highlightedOutline, 1)); + painter->drawPath(circle); + + if (state & (State_On )) { + circle = QPainterPath(); + circle.addEllipse(rect.center() + QPoint(1, 1), 2.8, 2.8); + QColor checkMarkColor = option->palette.text().color().darker(120); + checkMarkColor.setAlpha(200); + painter->setPen(checkMarkColor); + checkMarkColor.setAlpha(180); + painter->setBrush(checkMarkColor); + painter->drawPath(circle); + } + } + painter->restore(); + break; + case PE_IndicatorToolBarHandle: + { + //draw grips + if (option->state & State_Horizontal) { + for (int i = -3 ; i < 2 ; i += 3) { + for (int j = -8 ; j < 10 ; j += 3) { + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade()); + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade()); + } + } + } else { //vertical toolbar + for (int i = -6 ; i < 12 ; i += 3) { + for (int j = -3 ; j < 2 ; j += 3) { + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade()); + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade()); + } + } + } + break; + } + case PE_FrameDefaultButton: + break; + case PE_FrameFocusRect: + if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(option)) { + //### check for d->alt_down + if (!(fropt->state & State_KeyboardFocusChange)) + return; + QRect rect = option->rect; + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + QColor fillcolor = highlightedOutline; + fillcolor.setAlpha(80); + painter->setPen(fillcolor.darker(120)); + fillcolor.setAlpha(30); + QLinearGradient gradient(rect.topLeft(), rect.bottomLeft()); + gradient.setColorAt(0, fillcolor.lighter(160)); + gradient.setColorAt(1, fillcolor); + painter->setBrush(gradient); + painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1); + painter->restore(); + } + break; + case PE_PanelButtonCommand: + { + bool isDefault = false; + bool isFlat = false; + bool isDown = (option->state & State_Sunken) || (option->state & State_On); + QRect r; + + if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton*>(option)) { + isDefault = (button->features & QStyleOptionButton::DefaultButton) && (button->state & State_Enabled); + isFlat = (button->features & QStyleOptionButton::Flat); + } + + if (isFlat && !isDown) { + if (isDefault) { + r = option->rect.adjusted(0, 1, 0, -1); + painter->setPen(QPen(Qt::black, 0)); + const QLine lines[4] = { + QLine(QPoint(r.left() + 2, r.top()), + QPoint(r.right() - 2, r.top())), + QLine(QPoint(r.left(), r.top() + 2), + QPoint(r.left(), r.bottom() - 2)), + QLine(QPoint(r.right(), r.top() + 2), + QPoint(r.right(), r.bottom() - 2)), + QLine(QPoint(r.left() + 2, r.bottom()), + QPoint(r.right() - 2, r.bottom())) + }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + QPoint(r.right() - 1, r.bottom() - 1), + QPoint(r.right() - 1, r.top() + 1), + QPoint(r.left() + 1, r.bottom() - 1), + QPoint(r.left() + 1, r.top() + 1) + }; + painter->drawPoints(points, 4); + } + return; + } + + BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("pushbutton-%1").arg(isDefault)) + r = rect.adjusted(0, 1, -1, 0); + + bool isEnabled = option->state & State_Enabled; + bool hasFocus = (option->state & State_HasFocus && option->state & State_KeyboardFocusChange); + QColor buttonColor = d->buttonColor(option->palette); + + QColor darkOutline = outline; + if (hasFocus | isDefault) { + darkOutline = highlightedOutline; + } + + if (isDefault) + buttonColor = mergedColors(buttonColor, highlightedOutline.lighter(130), 90); + + p->setRenderHint(QPainter::Antialiasing, true); + p->translate(0.5, -0.5); + + QLinearGradient gradient = qt_fusion_gradient(rect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104)); + p->setPen(Qt::transparent); + p->setBrush(isDown ? QBrush(buttonColor.darker(110)) : gradient); + p->drawRoundedRect(r, 2.0, 2.0); + p->setBrush(Qt::NoBrush); + + // Outline + p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline, 1)); + p->drawRoundedRect(r, 2.0, 2.0); + + p->setPen(d->innerContrastLine()); + p->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2.0, 2.0); + + END_STYLE_PIXMAPCACHE + } + break; + case PE_FrameTabWidget: + painter->save(); + painter->fillRect(option->rect.adjusted(0, 0, -1, -1), tabFrameColor); + if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) { + QColor borderColor = outline.lighter(110); + QRect rect = option->rect.adjusted(0, 0, -1, -1); + + // Shadow outline + if (twf->shape != QTabBar::RoundedSouth) { + rect.adjust(0, 0, 0, -1); + QColor alphaShadow(Qt::black); + alphaShadow.setAlpha(15); + painter->setPen(alphaShadow); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); painter->setPen(borderColor); + } + + // outline + painter->setPen(outline); + painter->drawRect(rect); + + // Inner frame highlight + painter->setPen(d->innerContrastLine()); + painter->drawRect(rect.adjusted(1, 1, -1, -1)); + + } + painter->restore(); + break ; + + case PE_FrameStatusBarItem: + break; + case PE_IndicatorTabClose: + { + Q_D(const QFusionStyle); + if (d->tabBarcloseButtonIcon.isNull()) + d->tabBarcloseButtonIcon = standardIcon(SP_DialogCloseButton, option, widget); + if ((option->state & State_Enabled) && (option->state & State_MouseOver)) + proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget); + QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On); + proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap); + } + break; + case PE_PanelMenu: { + painter->save(); + QColor menuBackground = option->palette.base().color().lighter(108); + QColor borderColor = option->palette.background().color().darker(160); + painter->setPen(borderColor); + painter->setBrush(menuBackground); + painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); + painter->restore(); + } + break; + + default: + QCommonStyle::drawPrimitive(elem, option, painter, widget); + break; + } +} + +/*! + \reimp +*/ +void QFusionStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, + const QWidget *widget) const +{ + Q_D (const QFusionStyle); + QRect rect = option->rect; + QColor outline = d->outline(option->palette); + QColor highlightedOutline = d->highlightedOutline(option->palette); + QColor shadow = d->darkShade(); + + switch (element) { + case CE_ComboBoxLabel: + if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { + QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget); + painter->save(); + painter->setClipRect(editRect); + if (!cb->currentIcon.isNull()) { + QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode); + QRect iconRect(editRect); + iconRect.setWidth(cb->iconSize.width() + 4); + iconRect = alignedRect(cb->direction, + Qt::AlignLeft | Qt::AlignVCenter, + iconRect.size(), editRect); + if (cb->editable) + painter->fillRect(iconRect, cb->palette.brush(QPalette::Base)); + proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap); + + if (cb->direction == Qt::RightToLeft) + editRect.translate(-4 - cb->iconSize.width(), 0); + else + editRect.translate(cb->iconSize.width() + 4, 0); + } + if (!cb->currentText.isEmpty() && !cb->editable) { + proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0), + visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter), + cb->palette, cb->state & State_Enabled, cb->currentText, + cb->editable ? QPalette::Text : QPalette::ButtonText); + } + painter->restore(); + } + break; + case CE_Splitter: + { + // Dont draw handle for single pixel splitters + if (option->rect.width() > 1 && option->rect.height() > 1) { + //draw grips + if (option->state & State_Horizontal) { + for (int j = -6 ; j< 12 ; j += 3) { + painter->fillRect(rect.center().x() + 1, rect.center().y() + j, 2, 2, d->lightShade()); + painter->fillRect(rect.center().x() + 1, rect.center().y() + j, 1, 1, d->darkShade()); + } + } else { + for (int i = -6; i< 12 ; i += 3) { + painter->fillRect(rect.center().x() + i, rect.center().y(), 2, 2, d->lightShade()); + painter->fillRect(rect.center().x() + i, rect.center().y(), 1, 1, d->darkShade()); + } + } + } + break; + } + case CE_RubberBand: + if (qstyleoption_cast<const QStyleOptionRubberBand *>(option)) { + QColor highlight = option->palette.color(QPalette::Active, QPalette::Highlight); + painter->save(); + QColor penColor = highlight.darker(120); + penColor.setAlpha(180); + painter->setPen(penColor); + QColor dimHighlight(qMin(highlight.red()/2 + 110, 255), + qMin(highlight.green()/2 + 110, 255), + qMin(highlight.blue()/2 + 110, 255)); + dimHighlight.setAlpha(widget && widget->isTopLevel() ? 255 : 80); + QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y())); + gradient.setColorAt(0, dimHighlight.lighter(120)); + gradient.setColorAt(1, dimHighlight); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + painter->setBrush(dimHighlight); + painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 1, 1); + QColor innerLine = Qt::white; + innerLine.setAlpha(40); + painter->setPen(innerLine); + painter->drawRoundedRect(option->rect.adjusted(1, 1, -2, -2), 1, 1); + painter->restore(); + return; + } + case CE_SizeGrip: + painter->save(); + { + //draw grips + for (int i = -6; i< 12 ; i += 3) { + for (int j = -6 ; j< 12 ; j += 3) { + if ((option->direction == Qt::LeftToRight && i > -j) || (option->direction == Qt::RightToLeft && j > i) ) { + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 2, 2, d->lightShade()); + painter->fillRect(rect.center().x() + i, rect.center().y() + j, 1, 1, d->darkShade()); + } + } + } + } + painter->restore(); + break; + case CE_ToolBar: + if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) { + // Reserve the beveled appearance only for mainwindow toolbars + if (!(widget && qobject_cast<const QMainWindow*> (widget->parentWidget()))) + break; + + // Draws the light line above and the dark line below menu bars and + // tool bars. + QLinearGradient gradient(option->rect.topLeft(), option->rect.bottomLeft()); + if (!option->state & State_Horizontal) + gradient = QLinearGradient(rect.left(), rect.center().y(), + rect.right(), rect.center().y()); + gradient.setColorAt(0, option->palette.window().color().lighter(104)); + gradient.setColorAt(1, option->palette.window().color()); + painter->fillRect(option->rect, gradient); + + QColor light = d->lightShade(); + QColor shadow = d->darkShade(); + + QPen oldPen = painter->pen(); + if (toolBar->toolBarArea == Qt::TopToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::End + || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) { + // The end and onlyone top toolbar lines draw a double + // line at the bottom to blend with the central + // widget. + painter->setPen(light); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + painter->setPen(shadow); + painter->drawLine(option->rect.left(), option->rect.bottom() - 1, + option->rect.right(), option->rect.bottom() - 1); + } else { + // All others draw a single dark line at the bottom. + painter->setPen(shadow); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + // All top toolbar lines draw a light line at the top. + painter->setPen(light); + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + } else if (toolBar->toolBarArea == Qt::BottomToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::End + || toolBar->positionOfLine == QStyleOptionToolBar::Middle) { + // The end and middle bottom tool bar lines draw a dark + // line at the bottom. + painter->setPen(shadow); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::Beginning + || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) { + // The beginning and only one tool bar lines draw a + // double line at the bottom to blend with the + // status bar. + // ### The styleoption could contain whether the + // main window has a menu bar and a status bar, and + // possibly dock widgets. + painter->setPen(shadow); + painter->drawLine(option->rect.left(), option->rect.bottom() - 1, + option->rect.right(), option->rect.bottom() - 1); + painter->setPen(light); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::End) { + painter->setPen(shadow); + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + painter->setPen(light); + painter->drawLine(option->rect.left(), option->rect.top() + 1, + option->rect.right(), option->rect.top() + 1); + + } else { + // All other bottom toolbars draw a light line at the top. + painter->setPen(light); + painter->drawLine(option->rect.topLeft(), option->rect.topRight()); + } + } + if (toolBar->toolBarArea == Qt::LeftToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::Middle + || toolBar->positionOfLine == QStyleOptionToolBar::End) { + // The middle and left end toolbar lines draw a light + // line to the left. + painter->setPen(light); + painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::End) { + // All other left toolbar lines draw a dark line to the right + painter->setPen(shadow); + painter->drawLine(option->rect.right() - 1, option->rect.top(), + option->rect.right() - 1, option->rect.bottom()); + painter->setPen(light); + painter->drawLine(option->rect.topRight(), option->rect.bottomRight()); + } else { + // All other left toolbar lines draw a dark line to the right + painter->setPen(shadow); + painter->drawLine(option->rect.topRight(), option->rect.bottomRight()); + } + } else if (toolBar->toolBarArea == Qt::RightToolBarArea) { + if (toolBar->positionOfLine == QStyleOptionToolBar::Middle + || toolBar->positionOfLine == QStyleOptionToolBar::End) { + // Right middle and end toolbar lines draw the dark right line + painter->setPen(shadow); + painter->drawLine(option->rect.topRight(), option->rect.bottomRight()); + } + if (toolBar->positionOfLine == QStyleOptionToolBar::End + || toolBar->positionOfLine == QStyleOptionToolBar::OnlyOne) { + // The right end and single toolbar draws the dark + // line on its left edge + painter->setPen(shadow); + painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft()); + // And a light line next to it + painter->setPen(light); + painter->drawLine(option->rect.left() + 1, option->rect.top(), + option->rect.left() + 1, option->rect.bottom()); + } else { + // Other right toolbars draw a light line on its left edge + painter->setPen(light); + painter->drawLine(option->rect.topLeft(), option->rect.bottomLeft()); + } + } + painter->setPen(oldPen); + } + break; + case CE_DockWidgetTitle: + painter->save(); + if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) { + bool verticalTitleBar = dwOpt->verticalTitleBar; + + QRect titleRect = subElementRect(SE_DockWidgetTitleBarText, option, widget); + if (verticalTitleBar) { + QRect rect = dwOpt->rect; + QRect r = rect; + QSize s = r.size(); + s.transpose(); + r.setSize(s); + titleRect = QRect(r.left() + rect.bottom() + - titleRect.bottom(), + r.top() + titleRect.left() - rect.left(), + titleRect.height(), titleRect.width()); + } + + if (!dwOpt->title.isEmpty()) { + QString titleText + = painter->fontMetrics().elidedText(dwOpt->title, + Qt::ElideRight, titleRect.width()); + proxy()->drawItemText(painter, + titleRect, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette, + dwOpt->state & State_Enabled, titleText, + QPalette::WindowText); + } + } + painter->restore(); + break; + case CE_HeaderSection: + painter->save(); + // Draws the header in tables. + if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size()); + pixmapName += QString::number(- int(header->position)); + pixmapName += QString::number(- int(header->orientation)); + + QPixmap cache; + if (!QPixmapCache::find(pixmapName, cache)) { + cache = styleCachePixmap(rect.size()); + cache.fill(Qt::transparent); + QRect pixmapRect(0, 0, rect.width(), rect.height()); + QPainter cachePainter(&cache); + QColor buttonColor = d->buttonColor(option->palette); + QColor gradientStopColor; + QColor gradientStartColor = buttonColor.lighter(104); + gradientStopColor = buttonColor.darker(102); + QLinearGradient gradient(pixmapRect.topLeft(), pixmapRect.bottomLeft()); + + if (option->palette.background().gradient()) { + gradient.setStops(option->palette.background().gradient()->stops()); + } else { + QColor midColor1 = mergedColors(gradientStartColor, gradientStopColor, 60); + QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40); + gradient.setColorAt(0, gradientStartColor); + gradient.setColorAt(0.5, midColor1); + gradient.setColorAt(0.501, midColor2); + gradient.setColorAt(0.92, gradientStopColor); + gradient.setColorAt(1, gradientStopColor.darker(104)); + } + cachePainter.fillRect(pixmapRect, gradient); + cachePainter.setPen(d->innerContrastLine()); + cachePainter.setBrush(Qt::NoBrush); + cachePainter.drawLine(pixmapRect.topLeft(), pixmapRect.topRight()); + cachePainter.setPen(d->outline(option->palette)); + cachePainter.drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight()); + + if (header->orientation == Qt::Horizontal && + header->position != QStyleOptionHeader::End && + header->position != QStyleOptionHeader::OnlyOneSection) { + cachePainter.setPen(QColor(0, 0, 0, 40)); + cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight() + QPoint(0, -1)); + cachePainter.setPen(d->innerContrastLine()); + cachePainter.drawLine(pixmapRect.topRight() + QPoint(-1, 0), pixmapRect.bottomRight() + QPoint(-1, -1)); + } else if (header->orientation == Qt::Vertical) { + cachePainter.setPen(d->outline(option->palette)); + cachePainter.drawLine(pixmapRect.topRight(), pixmapRect.bottomRight()); + } + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(rect.topLeft(), cache); + } + painter->restore(); + break; + case CE_ProgressBarGroove: + painter->save(); + { + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + + QColor shadowAlpha = Qt::black; + shadowAlpha.setAlpha(16); + painter->setPen(shadowAlpha); + painter->drawLine(rect.topLeft() - QPoint(0, 1), rect.topRight() - QPoint(0, 1)); + + painter->setBrush(option->palette.base()); + painter->setPen(QPen(outline, 0)); + painter->drawRoundedRect(rect.adjusted(0, 0, -1, -1), 2, 2); + + // Inner shadow + painter->setPen(d->topShadow()); + painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), + QPoint(rect.right() - 1, rect.top() + 1)); + } + painter->restore(); + break; + case CE_ProgressBarContents: + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { + bool vertical = false; + bool inverted = false; + bool indeterminate = (bar->minimum == 0 && bar->maximum == 0); + bool complete = bar->progress == bar->maximum; + + // Get extra style options if version 2 + vertical = (bar->orientation == Qt::Vertical); + inverted = bar->invertedAppearance; + + // If the orientation is vertical, we use a transform to rotate + // the progress bar 90 degrees clockwise. This way we can use the + // same rendering code for both orientations. + if (vertical) { + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + QTransform m = QTransform::fromTranslate(rect.height()-1, -1.0); + m.rotate(90.0); + painter->setTransform(m, true); + } + + int maxWidth = rect.width(); + int minWidth = 0; + qreal progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar + int progressBarWidth = (progress - bar->minimum) * qreal(maxWidth) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum); + int width = indeterminate ? maxWidth : qMax(minWidth, progressBarWidth); + + bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical; + if (inverted) + reverse = !reverse; + + int step = 0; + QRect progressBar; + QColor highlight = d->highlight(option->palette); + QColor highlightedoutline = highlight.darker(140); + if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb())) + outline = highlightedoutline; + + if (!indeterminate) { + QColor innerShadow(Qt::black); + innerShadow.setAlpha(35); + painter->setPen(innerShadow); + if (!reverse) { + progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1); + if (!complete) { + painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0)); + painter->setPen(QPen(highlight.darker(140), 0)); + painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0)); + } + } else { + progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1); + if (!complete) { + painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0)); + painter->setPen(QPen(highlight.darker(140), 0)); + painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0)); + } + } + } else { + progressBar.setRect(rect.left(), rect.top(), rect.width() - 1, rect.height() - 1); + } + + if (indeterminate || bar->progress > bar->minimum) { + + painter->setPen(QPen(outline, 0)); + + QColor highlightedGradientStartColor = highlight.lighter(120); + QColor highlightedGradientStopColor = highlight; + QLinearGradient gradient(rect.topLeft(), QPoint(rect.bottomLeft().x(), rect.bottomLeft().y())); + gradient.setColorAt(0, highlightedGradientStartColor); + gradient.setColorAt(1, highlightedGradientStopColor); + + painter->setBrush(gradient); + + painter->save(); + if (!complete && !indeterminate) + painter->setClipRect(progressBar.adjusted(-1, -1, -1, 1)); + QRect fillRect = progressBar.adjusted( !indeterminate && !complete && reverse ? -2 : 0, 0, + indeterminate || complete || reverse ? 0 : 2, 0); + painter->drawRoundedRect(fillRect, 2, 2); + painter->restore(); + + painter->setBrush(Qt::NoBrush); + painter->setPen(QColor(255, 255, 255, 50)); + painter->drawRoundedRect(progressBar.adjusted(1, 1, -1, -1), 1, 1); + + if (!indeterminate) { + (const_cast<QFusionStylePrivate*>(d))->stopAnimation(option->styleObject); + } else { + highlightedGradientStartColor.setAlpha(120); + painter->setPen(QPen(highlightedGradientStartColor, 9.0)); + painter->setClipRect(progressBar.adjusted(1, 1, -1, -1)); +#ifndef QT_NO_ANIMATION + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(option->styleObject))) + step = animation->animationStep() % 22; + else + (const_cast<QFusionStylePrivate*>(d))->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject)); +#endif + for (int x = progressBar.left() - rect.height(); x < rect.right() ; x += 22) + painter->drawLine(x + step, progressBar.bottom() + 1, + x + rect.height() + step, progressBar.top() - 2); + } + } + } + painter->restore(); + break; + case CE_ProgressBarLabel: + if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { + QRect leftRect; + QRect rect = bar->rect; + QColor textColor = option->palette.text().color(); + QColor alternateTextColor = option->palette.highlightedText().color(); + + painter->save(); + bool vertical = false, inverted = false; + vertical = (bar->orientation == Qt::Vertical); + inverted = bar->invertedAppearance; + if (vertical) + rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height + const int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) * rect.width() / + qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum); + if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) + leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height()); + if (vertical) + leftRect.translate(rect.width() - progressIndicatorPos, 0); + + bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) || + ((bar->direction == Qt::LeftToRight) && inverted))); + + QRegion rightRect = rect; + rightRect = rightRect.subtracted(leftRect); + painter->setClipRegion(rightRect); + painter->setPen(flip ? alternateTextColor : textColor); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + if (!leftRect.isNull()) { + painter->setPen(flip ? textColor : alternateTextColor); + painter->setClipRect(leftRect); + painter->drawText(rect, bar->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); + } + painter->restore(); + } + break; + case CE_MenuBarItem: + painter->save(); + if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) + { + QStyleOptionMenuItem item = *mbi; + item.rect = mbi->rect.adjusted(0, 1, 0, -3); + QColor highlightOutline = option->palette.highlight().color().darker(125); + painter->fillRect(rect, option->palette.window()); + + QCommonStyle::drawControl(element, &item, painter, widget); + + bool act = mbi->state & State_Selected && mbi->state & State_Sunken; + bool dis = !(mbi->state & State_Enabled); + + QRect r = option->rect; + if (act) { + painter->setBrush(option->palette.highlight().color()); + painter->setPen(QPen(highlightOutline, 0)); + painter->drawRect(r.adjusted(0, 0, -1, -1)); + + // painter->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2); + + //draw text + QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText; + uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, mbi, widget)) + alignment |= Qt::TextHideMnemonic; + proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); + } else { + + QColor shadow = mergedColors(option->palette.background().color().darker(120), + outline.lighter(140), 60); + painter->setPen(QPen(shadow)); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + } + painter->restore(); + break; + case CE_MenuItem: + painter->save(); + // Draws one item in a popup menu. + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { + QColor highlightOutline = highlightedOutline; + QColor highlight = option->palette.highlight().color(); + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + int w = 0; + if (!menuItem->text.isEmpty()) { + painter->setFont(menuItem->font); + proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter, + menuItem->palette, menuItem->state & State_Enabled, menuItem->text, + QPalette::Text); + w = menuItem->fontMetrics.width(menuItem->text) + 5; + } + painter->setPen(shadow.lighter(106)); + bool reverse = menuItem->direction == Qt::RightToLeft; + painter->drawLine(menuItem->rect.left() + 5 + (reverse ? 0 : w), menuItem->rect.center().y(), + menuItem->rect.right() - 5 - (reverse ? w : 0), menuItem->rect.center().y()); + painter->restore(); + break; + } + bool selected = menuItem->state & State_Selected && menuItem->state & State_Enabled; + if (selected) { + QRect r = option->rect; + painter->fillRect(r, highlight); + painter->setPen(QPen(highlightOutline, 0)); + const QLine lines[4] = { + QLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())), + QLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())), + QLine(QPoint(r.left(), r.top()), QPoint(r.left(), r.bottom())), + QLine(QPoint(r.right() , r.top()), QPoint(r.right(), r.bottom())), + }; + painter->drawLines(lines, 4); + } + bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable; + bool checked = menuItem->checked; + bool sunken = menuItem->state & State_Sunken; + bool enabled = menuItem->state & State_Enabled; + + bool ignoreCheckMark = false; + int checkcol = qMax(menuItem->maxIconWidth, 20); + + if (qobject_cast<const QComboBox*>(widget)) + ignoreCheckMark = true; //ignore the checkmarks provided by the QComboMenuDelegate + + if (!ignoreCheckMark) { + // Check + QRect checkRect(option->rect.left() + 7, option->rect.center().y() - 6, 14, 14); + checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect); + if (checkable) { + if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) { + // Radio button + if (checked || sunken) { + painter->setRenderHint(QPainter::Antialiasing); + painter->setPen(Qt::NoPen); + + QPalette::ColorRole textRole = !enabled ? QPalette::Text: + selected ? QPalette::HighlightedText : QPalette::ButtonText; + painter->setBrush(option->palette.brush( option->palette.currentColorGroup(), textRole)); + painter->drawEllipse(checkRect.adjusted(4, 4, -4, -4)); + } + } else { + // Check box + if (menuItem->icon.isNull()) { + QStyleOptionButton box; + box.QStyleOption::operator=(*option); + box.rect = checkRect; + if (checked) + box.state |= State_On; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + } + } + } else { //ignore checkmark + if (menuItem->icon.isNull()) + checkcol = 0; + else + checkcol = menuItem->maxIconWidth; + } + + // Text and icon, ripped from windows style + bool dis = !(menuItem->state & State_Enabled); + bool act = menuItem->state & State_Selected; + const QStyleOption *opt = option; + const QStyleOptionMenuItem *menuitem = menuItem; + + QPainter *p = painter; + QRect vCheckRect = visualRect(opt->direction, menuitem->rect, + QRect(menuitem->rect.x() + 4, menuitem->rect.y(), + checkcol, menuitem->rect.height())); + if (!menuItem->icon.isNull()) { + QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal; + if (act && !dis) + mode = QIcon::Active; + QPixmap pixmap; + + int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget); + QSize iconSize(smallIconSize, smallIconSize); + if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget)) + iconSize = combo->iconSize(); + if (checked) + pixmap = menuItem->icon.pixmap(iconSize, mode, QIcon::On); + else + pixmap = menuItem->icon.pixmap(iconSize, mode); + + int pixw = pixmap.width(); + int pixh = pixmap.height(); + + QRect pmr(0, 0, pixw, pixh); + pmr.moveCenter(vCheckRect.center()); + painter->setPen(menuItem->palette.text().color()); + if (checkable && checked) { + QStyleOption opt = *option; + if (act) { + QColor activeColor = mergedColors(option->palette.background().color(), + option->palette.highlight().color()); + opt.palette.setBrush(QPalette::Button, activeColor); + } + opt.state |= State_Sunken; + opt.rect = vCheckRect; + proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget); + } + painter->drawPixmap(pmr.topLeft(), pixmap); + } + if (selected) { + painter->setPen(menuItem->palette.highlightedText().color()); + } else { + painter->setPen(menuItem->palette.text().color()); + } + int x, y, w, h; + menuitem->rect.getRect(&x, &y, &w, &h); + int tab = menuitem->tabWidth; + QColor discol; + if (dis) { + discol = menuitem->palette.text().color(); + p->setPen(discol); + } + int xm = windowsItemFrame + checkcol + windowsItemHMargin + 2; + int xpos = menuitem->rect.x() + xm; + + QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); + QString s = menuitem->text; + if (!s.isEmpty()) { // draw text + p->save(); + int t = s.indexOf(QLatin1Char('\t')); + int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; + if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) + text_flags |= Qt::TextHideMnemonic; + text_flags |= Qt::AlignLeft; + if (t >= 0) { + QRect vShortcutRect = visualRect(opt->direction, menuitem->rect, + QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, s.mid(t + 1)); + p->setPen(discol); + } + p->drawText(vShortcutRect, text_flags, s.mid(t + 1)); + s = s.left(t); + } + QFont font = menuitem->font; + // font may not have any "hard" flags set. We override + // the point size so that when it is resolved against the device, this font will win. + // This is mainly to handle cases where someone sets the font on the window + // and then the combo inherits it and passes it onward. At that point the resolve mask + // is very, very weak. This makes it stonger. + font.setPointSizeF(QFontInfo(menuItem->font).pointSizeF()); + + if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) + font.setBold(true); + + p->setFont(font); + if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) { + p->setPen(menuitem->palette.light().color()); + p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, s.left(t)); + p->setPen(discol); + } + p->drawText(vTextRect, text_flags, s.left(t)); + p->restore(); + } + + // Arrow + if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow + int dim = (menuItem->rect.height() - 4) / 2; + PrimitiveElement arrow; + arrow = QApplication::isRightToLeft() ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; + int xpos = menuItem->rect.left() + menuItem->rect.width() - 3 - dim; + QRect vSubMenuRect = visualRect(option->direction, menuItem->rect, + QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim)); + QStyleOptionMenuItem newMI = *menuItem; + newMI.rect = vSubMenuRect; + newMI.state = !enabled ? State_None : State_Enabled; + if (selected) + newMI.palette.setColor(QPalette::Foreground, + newMI.palette.highlightedText().color()); + proxy()->drawPrimitive(arrow, &newMI, painter, widget); + } + } + painter->restore(); + break; + case CE_MenuHMargin: + case CE_MenuVMargin: + break; + case CE_MenuEmptyArea: + break; + case CE_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { + proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget); + QStyleOptionButton subopt = *btn; + subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); + proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget); + } + break; + case CE_PushButtonLabel: + if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) { + QRect ir = button->rect; + uint tf = Qt::AlignVCenter; + if (styleHint(SH_UnderlineShortcut, button, widget)) + tf |= Qt::TextShowMnemonic; + else + tf |= Qt::TextHideMnemonic; + + if (!button->icon.isNull()) { + //Center both icon and text + QPoint point; + + QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal + : QIcon::Disabled; + if (mode == QIcon::Normal && button->state & State_HasFocus) + mode = QIcon::Active; + QIcon::State state = QIcon::Off; + if (button->state & State_On) + state = QIcon::On; + + QPixmap pixmap = button->icon.pixmap(button->iconSize, mode, state); + int w = pixmap.width(); + int h = pixmap.height(); + + if (!button->text.isEmpty()) + w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2; + + point = QPoint(ir.x() + ir.width() / 2 - w / 2, + ir.y() + ir.height() / 2 - h / 2); + + if (button->direction == Qt::RightToLeft) + point.rx() += pixmap.width(); + + painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap); + + if (button->direction == Qt::RightToLeft) + ir.translate(-point.x() - 2, 0); + else + ir.translate(point.x() + pixmap.width(), 0); + + // left-align text if there is + if (!button->text.isEmpty()) + tf |= Qt::AlignLeft; + + } else { + tf |= Qt::AlignHCenter; + } + + if (button->features & QStyleOptionButton::HasMenu) + ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0); + proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled), + button->text, QPalette::ButtonText); + } + break; + case CE_MenuBarEmptyArea: + painter->save(); + { + painter->fillRect(rect, option->palette.window()); + if (widget && qobject_cast<const QMainWindow *>(widget->parentWidget())) { + QColor shadow = mergedColors(option->palette.background().color().darker(120), + outline.lighter(140), 60); + painter->setPen(QPen(shadow)); + painter->drawLine(option->rect.bottomLeft(), option->rect.bottomRight()); + } + } + painter->restore(); + break; + case CE_TabBarTabShape: + painter->save(); + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) { + + bool rtlHorTabs = (tab->direction == Qt::RightToLeft + && (tab->shape == QTabBar::RoundedNorth + || tab->shape == QTabBar::RoundedSouth)); + bool selected = tab->state & State_Selected; + bool lastTab = ((!rtlHorTabs && tab->position == QStyleOptionTab::End) + || (rtlHorTabs + && tab->position == QStyleOptionTab::Beginning)); + bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab; + int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget); + rect = option->rect.adjusted(0, 0, (onlyOne || lastTab) ? 0 : tabOverlap, 0); + + QRect r2(rect); + int x1 = r2.left(); + int x2 = r2.right(); + int y1 = r2.top(); + int y2 = r2.bottom(); + + painter->setPen(d->innerContrastLine()); + + QTransform rotMatrix; + bool flip = false; + painter->setPen(shadow); + + switch (tab->shape) { + case QTabBar::RoundedNorth: + break; + case QTabBar::RoundedSouth: + rotMatrix.rotate(180); + rotMatrix.translate(0, -rect.height() + 1); + rotMatrix.scale(-1, 1); + painter->setTransform(rotMatrix, true); + break; + case QTabBar::RoundedWest: + rotMatrix.rotate(180 + 90); + rotMatrix.scale(-1, 1); + flip = true; + painter->setTransform(rotMatrix, true); + break; + case QTabBar::RoundedEast: + rotMatrix.rotate(90); + rotMatrix.translate(0, - rect.width() + 1); + flip = true; + painter->setTransform(rotMatrix, true); + break; + default: + painter->restore(); + QCommonStyle::drawControl(element, tab, painter, widget); + return; + } + + if (flip) { + QRect tmp = rect; + rect = QRect(tmp.y(), tmp.x(), tmp.height(), tmp.width()); + int temp = x1; + x1 = y1; + y1 = temp; + temp = x2; + x2 = y2; + y2 = temp; + } + + painter->setRenderHint(QPainter::Antialiasing, true); + painter->translate(0.5, 0.5); + + QColor tabFrameColor = tab->features & QStyleOptionTab::HasFrame ? + d->tabFrameColor(option->palette) : + option->palette.window().color(); + + QLinearGradient fillGradient(rect.topLeft(), rect.bottomLeft()); + QLinearGradient outlineGradient(rect.topLeft(), rect.bottomLeft()); + QPen outlinePen = outline.lighter(110); + if (selected) { + fillGradient.setColorAt(0, tabFrameColor.lighter(104)); + // QColor highlight = option->palette.highlight().color(); + // if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) { + // fillGradient.setColorAt(0, highlight.lighter(130)); + // outlineGradient.setColorAt(0, highlight.darker(130)); + // fillGradient.setColorAt(0.14, highlight); + // outlineGradient.setColorAt(0.14, highlight.darker(130)); + // fillGradient.setColorAt(0.1401, tabFrameColor); + // outlineGradient.setColorAt(0.1401, highlight.darker(130)); + // } + fillGradient.setColorAt(1, tabFrameColor); + outlineGradient.setColorAt(1, outline); + outlinePen = QPen(outlineGradient, 1); + } else { + fillGradient.setColorAt(0, tabFrameColor.darker(108)); + fillGradient.setColorAt(0.85, tabFrameColor.darker(108)); + fillGradient.setColorAt(1, tabFrameColor.darker(116)); + } + + QRect drawRect = rect.adjusted(0, selected ? 0 : 2, 0, 3); + painter->setPen(outlinePen); + painter->save(); + painter->setClipRect(rect.adjusted(-1, -1, 1, selected ? -2 : -3)); + painter->setBrush(fillGradient); + painter->drawRoundedRect(drawRect.adjusted(0, 0, -1, -1), 2.0, 2.0); + painter->setBrush(Qt::NoBrush); + painter->setPen(d->innerContrastLine()); + painter->drawRoundedRect(drawRect.adjusted(1, 1, -2, -1), 2.0, 2.0); + painter->restore(); + + if (selected) { + painter->fillRect(rect.left() + 1, rect.bottom() - 1, rect.width() - 2, rect.bottom() - 1, tabFrameColor); + painter->fillRect(QRect(rect.bottomRight() + QPoint(-2, -1), QSize(1, 1)), d->innerContrastLine()); + painter->fillRect(QRect(rect.bottomLeft() + QPoint(0, -1), QSize(1, 1)), d->innerContrastLine()); + painter->fillRect(QRect(rect.bottomRight() + QPoint(-1, -1), QSize(1, 1)), d->innerContrastLine()); + } + } + painter->restore(); + break; + default: + QCommonStyle::drawControl(element,option,painter,widget); + break; + } +} + +/*! + \reimp +*/ +QPalette QFusionStyle::standardPalette () const +{ + QPalette palette = QCommonStyle::standardPalette(); + palette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198)); + palette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(145, 141, 126)); + palette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 141, 126)); + + QColor backGround(239, 235, 231); + + QColor light = backGround.lighter(150); + QColor base = Qt::white; + QColor dark = QColor(170, 156, 143).darker(110); + dark = backGround.darker(150); + QColor darkDisabled = QColor(209, 200, 191).darker(110); + + //### Find the correct disabled text color + palette.setBrush(QPalette::Disabled, QPalette::Text, QColor(190, 190, 190)); + + palette.setBrush(QPalette::Window, backGround); + palette.setBrush(QPalette::Mid, backGround.darker(130)); + palette.setBrush(QPalette::Light, light); + + palette.setBrush(QPalette::Active, QPalette::Base, base); + palette.setBrush(QPalette::Inactive, QPalette::Base, base); + palette.setBrush(QPalette::Disabled, QPalette::Base, backGround); + + palette.setBrush(QPalette::Midlight, palette.mid().color().lighter(110)); + + palette.setBrush(QPalette::All, QPalette::Dark, dark); + palette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled); + + QColor button = backGround; + + palette.setBrush(QPalette::Button, button); + + QColor shadow = dark.darker(135); + palette.setBrush(QPalette::Shadow, shadow); + palette.setBrush(QPalette::Disabled, QPalette::Shadow, shadow.lighter(150)); + palette.setBrush(QPalette::HighlightedText, QColor(QRgb(0xffffffff))); + + return palette; +} + +/*! + \reimp +*/ +void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const +{ + + Q_D (const QFusionStyle); + + QColor buttonColor = d->buttonColor(option->palette); + QColor gradientStartColor = buttonColor.lighter(118); + QColor gradientStopColor = buttonColor; + QColor outline = d->outline(option->palette); + + QColor alphaCornerColor; + if (widget) { + // ### backgroundrole/foregroundrole should be part of the style option + alphaCornerColor = mergedColors(option->palette.color(widget->backgroundRole()), outline); + } else { + alphaCornerColor = mergedColors(option->palette.background().color(), outline); + } + + switch (control) { + case CC_GroupBox: + painter->save(); + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) { + // Draw frame + QRect textRect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget); + QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget); + + if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { + QStyleOptionFrame frame; + frame.QStyleOption::operator=(*groupBox); + frame.features = groupBox->features; + frame.lineWidth = groupBox->lineWidth; + frame.midLineWidth = groupBox->midLineWidth; + frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget); + proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); + } + + // Draw title + if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { + // groupBox->textColor gets the incorrect palette here + painter->setPen(QPen(option->palette.windowText(), 1)); + int alignment = int(groupBox->textAlignment); + if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, option, widget)) + alignment |= Qt::TextHideMnemonic; + + proxy()->drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignLeft | alignment, + groupBox->palette, groupBox->state & State_Enabled, groupBox->text, QPalette::NoRole); + + if (groupBox->state & State_HasFocus) { + QStyleOptionFocusRect fropt; + fropt.QStyleOption::operator=(*groupBox); + fropt.rect = textRect.translated(0, -2); + proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); + } + } + + // Draw checkbox + if (groupBox->subControls & SC_GroupBoxCheckBox) { + QStyleOptionButton box; + box.QStyleOption::operator=(*groupBox); + box.rect = checkBoxRect; + proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget); + } + } + painter->restore(); + break; + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + QPixmap cache; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size()); + if (!QPixmapCache::find(pixmapName, cache)) { + + cache = styleCachePixmap(spinBox->rect.size()); + cache.fill(Qt::transparent); + + QRect pixmapRect(0, 0, spinBox->rect.width(), spinBox->rect.height()); + QRect rect = pixmapRect; + QRect r = rect.adjusted(0, 1, 0, -1); + QPainter cachePainter(&cache); + QColor arrowColor = spinBox->palette.foreground().color(); + arrowColor.setAlpha(220); + + bool isEnabled = (spinBox->state & State_Enabled); + bool hover = isEnabled && (spinBox->state & State_MouseOver); + bool sunken = (spinBox->state & State_Sunken); + bool upIsActive = (spinBox->activeSubControls == SC_SpinBoxUp); + bool downIsActive = (spinBox->activeSubControls == SC_SpinBoxDown); + bool hasFocus = (option->state & State_HasFocus); + + QStyleOptionSpinBox spinBoxCopy = *spinBox; + spinBoxCopy.rect = pixmapRect; + QRect upRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget); + QRect downRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget); + + if (spinBox->frame) { + cachePainter.save(); + cachePainter.setRenderHint(QPainter::Antialiasing, true); + cachePainter.translate(0.5, 0.5); + + // Fill background + cachePainter.setPen(Qt::NoPen); + cachePainter.setBrush(option->palette.base()); + cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2); + + // Draw inner shadow + cachePainter.setPen(d->topShadow()); + cachePainter.drawLine(QPoint(r.left() + 2, r.top() + 1), QPoint(r.right() - 2, r.top() + 1)); + + // Draw button gradient + QColor buttonColor = d->buttonColor(option->palette); + QRect updownRect = upRect.adjusted(0, -2, 0, downRect.height() + 2); + QLinearGradient gradient = qt_fusion_gradient(updownRect, (isEnabled && option->state & State_MouseOver ) ? buttonColor : buttonColor.darker(104)); + + // Draw button gradient + cachePainter.setPen(Qt::NoPen); + cachePainter.setBrush(gradient); + + cachePainter.save(); + cachePainter.setClipRect(updownRect); + cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2); + cachePainter.setPen(QPen(d->innerContrastLine())); + cachePainter.setBrush(Qt::NoBrush); + cachePainter.drawRoundedRect(r.adjusted(1, 1, -2, -2), 2, 2); + cachePainter.restore(); + + if ((spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) && upIsActive) { + if (sunken) + cachePainter.fillRect(upRect.adjusted(0, -1, 0, 0), gradientStopColor.darker(110)); + else if (hover) + cachePainter.fillRect(upRect.adjusted(0, -1, 0, 0), d->innerContrastLine()); + } + + if ((spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) && downIsActive) { + if (sunken) + cachePainter.fillRect(downRect.adjusted(0, 0, 0, 1), gradientStopColor.darker(110)); + else if (hover) + cachePainter.fillRect(downRect.adjusted(0, 0, 0, 1), d->innerContrastLine()); + } + + cachePainter.setPen(hasFocus ? d->highlightedOutline(option->palette) : outline); + cachePainter.setBrush(Qt::NoBrush); + cachePainter.drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2); + if (hasFocus) { + QColor softHighlight = option->palette.highlight().color(); + softHighlight.setAlpha(40); + cachePainter.setPen(softHighlight); + cachePainter.drawRoundedRect(r.adjusted(1, 1, -2, -2), 1.7, 1.7); + } + cachePainter.restore(); + } + + // outline the up/down buttons + cachePainter.setPen(outline); + if (spinBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(upRect.right(), upRect.top() - 1, upRect.right(), downRect.bottom() + 1); + } else { + cachePainter.drawLine(upRect.left(), upRect.top() - 1, upRect.left(), downRect.bottom() + 1); + } + + if (upIsActive && sunken) { + cachePainter.setPen(gradientStopColor.darker(130)); + cachePainter.drawLine(downRect.left() + 1, downRect.top(), downRect.right(), downRect.top()); + cachePainter.drawLine(upRect.left() + 1, upRect.top(), upRect.left() + 1, upRect.bottom()); + cachePainter.drawLine(upRect.left() + 1, upRect.top() - 1, upRect.right(), upRect.top() - 1); + } + + if (downIsActive && sunken) { + cachePainter.setPen(gradientStopColor.darker(130)); + cachePainter.drawLine(downRect.left() + 1, downRect.top(), downRect.left() + 1, downRect.bottom() + 1); + cachePainter.drawLine(downRect.left() + 1, downRect.top(), downRect.right(), downRect.top()); + cachePainter.setPen(gradientStopColor.darker(110)); + cachePainter.drawLine(downRect.left() + 1, downRect.bottom() + 1, downRect.right(), downRect.bottom() + 1); + } + + QColor disabledColor = mergedColors(arrowColor, option->palette.button().color()); + if (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) { + int centerX = upRect.center().x(); + int centerY = upRect.center().y(); + + // plus/minus + cachePainter.setPen((spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor); + cachePainter.drawLine(centerX - 1, centerY, centerX + 3, centerY); + cachePainter.drawLine(centerX + 1, centerY - 2, centerX + 1, centerY + 2); + + centerX = downRect.center().x(); + centerY = downRect.center().y(); + cachePainter.setPen((spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor); + cachePainter.drawLine(centerX - 1, centerY, centerX + 3, centerY); + + } else if (spinBox->buttonSymbols == QAbstractSpinBox::UpDownArrows){ + // arrows + painter->setRenderHint(QPainter::SmoothPixmapTransform); + + QPixmap upArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), + (spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor); + + cachePainter.drawPixmap(QRect(upRect.center().x() - upArrow.width() / 4 + 1, + upRect.center().y() - upArrow.height() / 4 + 1, + upArrow.width()/2, upArrow.height()/2), upArrow); + + QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), + (spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor, 180); + cachePainter.drawPixmap(QRect(downRect.center().x() - downArrow.width() / 4 + 1, + downRect.center().y() - downArrow.height() / 4 + 1, + downArrow.width()/2, downArrow.height()/2), downArrow); + } + + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(spinBox->rect.topLeft(), cache); + } + break; + case CC_TitleBar: + painter->save(); + if (const QStyleOptionTitleBar *titleBar = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) { + const int buttonMargin = 5; + bool active = (titleBar->titleBarState & State_Active); + QRect fullRect = titleBar->rect; + QPalette palette = option->palette; + QColor highlight = option->palette.highlight().color(); + + QColor titleBarFrameBorder(active ? highlight.darker(180): outline.darker(110)); + QColor titleBarHighlight(active ? highlight.lighter(120): palette.background().color().lighter(120)); + QColor textColor(active ? 0xffffff : 0xff000000); + QColor textAlphaColor(active ? 0xffffff : 0xff000000 ); + + { + // Fill title bar gradient + QColor titlebarColor = QColor(active ? highlight: palette.background().color()); + QLinearGradient gradient(option->rect.center().x(), option->rect.top(), + option->rect.center().x(), option->rect.bottom()); + + gradient.setColorAt(0, titlebarColor.lighter(114)); + gradient.setColorAt(0.5, titlebarColor.lighter(102)); + gradient.setColorAt(0.51, titlebarColor.darker(104)); + gradient.setColorAt(1, titlebarColor); + painter->fillRect(option->rect.adjusted(1, 1, -1, 0), gradient); + + // Frame and rounded corners + painter->setPen(titleBarFrameBorder); + + // top outline + painter->drawLine(fullRect.left() + 5, fullRect.top(), fullRect.right() - 5, fullRect.top()); + painter->drawLine(fullRect.left(), fullRect.top() + 4, fullRect.left(), fullRect.bottom()); + const QPoint points[5] = { + QPoint(fullRect.left() + 4, fullRect.top() + 1), + QPoint(fullRect.left() + 3, fullRect.top() + 1), + QPoint(fullRect.left() + 2, fullRect.top() + 2), + QPoint(fullRect.left() + 1, fullRect.top() + 3), + QPoint(fullRect.left() + 1, fullRect.top() + 4) + }; + painter->drawPoints(points, 5); + + painter->drawLine(fullRect.right(), fullRect.top() + 4, fullRect.right(), fullRect.bottom()); + const QPoint points2[5] = { + QPoint(fullRect.right() - 3, fullRect.top() + 1), + QPoint(fullRect.right() - 4, fullRect.top() + 1), + QPoint(fullRect.right() - 2, fullRect.top() + 2), + QPoint(fullRect.right() - 1, fullRect.top() + 3), + QPoint(fullRect.right() - 1, fullRect.top() + 4) + }; + painter->drawPoints(points2, 5); + + // draw bottomline + painter->drawLine(fullRect.right(), fullRect.bottom(), fullRect.left(), fullRect.bottom()); + + // top highlight + painter->setPen(titleBarHighlight); + painter->drawLine(fullRect.left() + 6, fullRect.top() + 1, fullRect.right() - 6, fullRect.top() + 1); + } + // draw title + QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget); + painter->setPen(active? (titleBar->palette.text().color().lighter(120)) : + titleBar->palette.text().color() ); + // Note workspace also does elliding but it does not use the correct font + QString title = painter->fontMetrics().elidedText(titleBar->text, Qt::ElideRight, textRect.width() - 14); + painter->drawText(textRect.adjusted(1, 1, 1, 1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter)); + painter->setPen(Qt::white); + if (active) + painter->drawText(textRect, title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter)); + // min button + if ((titleBar->subControls & SC_TitleBarMinButton) && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) && + !(titleBar->titleBarState& Qt::WindowMinimized)) { + QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget); + if (minButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken); + qt_fusion_draw_mdibutton(painter, titleBar, minButtonRect, hover, sunken); + QRect minButtonIconRect = minButtonRect.adjusted(buttonMargin ,buttonMargin , -buttonMargin, -buttonMargin); + painter->setPen(textColor); + painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 3); + painter->drawLine(minButtonIconRect.center().x() - 2, minButtonIconRect.center().y() + 4, + minButtonIconRect.center().x() + 3, minButtonIconRect.center().y() + 4); + painter->setPen(textAlphaColor); + painter->drawLine(minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() - 3, minButtonIconRect.center().y() + 4); + painter->drawLine(minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 3, + minButtonIconRect.center().x() + 4, minButtonIconRect.center().y() + 4); + } + } + // max button + if ((titleBar->subControls & SC_TitleBarMaxButton) && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) && + !(titleBar->titleBarState & Qt::WindowMaximized)) { + QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget); + if (maxButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken); + qt_fusion_draw_mdibutton(painter, titleBar, maxButtonRect, hover, sunken); + + QRect maxButtonIconRect = maxButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin); + + painter->setPen(textColor); + painter->drawRect(maxButtonIconRect.adjusted(0, 0, -1, -1)); + painter->drawLine(maxButtonIconRect.left() + 1, maxButtonIconRect.top() + 1, + maxButtonIconRect.right() - 1, maxButtonIconRect.top() + 1); + painter->setPen(textAlphaColor); + const QPoint points[4] = { + maxButtonIconRect.topLeft(), + maxButtonIconRect.topRight(), + maxButtonIconRect.bottomLeft(), + maxButtonIconRect.bottomRight() + }; + painter->drawPoints(points, 4); + } + } + + // close button + if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) { + QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget); + if (closeButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken); + qt_fusion_draw_mdibutton(painter, titleBar, closeButtonRect, hover, sunken); + QRect closeIconRect = closeButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin); + painter->setPen(textAlphaColor); + const QLine lines[4] = { + QLine(closeIconRect.left() + 1, closeIconRect.top(), + closeIconRect.right(), closeIconRect.bottom() - 1), + QLine(closeIconRect.left(), closeIconRect.top() + 1, + closeIconRect.right() - 1, closeIconRect.bottom()), + QLine(closeIconRect.right() - 1, closeIconRect.top(), + closeIconRect.left(), closeIconRect.bottom() - 1), + QLine(closeIconRect.right(), closeIconRect.top() + 1, + closeIconRect.left() + 1, closeIconRect.bottom()) + }; + painter->drawLines(lines, 4); + const QPoint points[4] = { + closeIconRect.topLeft(), + closeIconRect.topRight(), + closeIconRect.bottomLeft(), + closeIconRect.bottomRight() + }; + painter->drawPoints(points, 4); + + painter->setPen(textColor); + painter->drawLine(closeIconRect.left() + 1, closeIconRect.top() + 1, + closeIconRect.right() - 1, closeIconRect.bottom() - 1); + painter->drawLine(closeIconRect.left() + 1, closeIconRect.bottom() - 1, + closeIconRect.right() - 1, closeIconRect.top() + 1); + } + } + + // normalize button + if ((titleBar->subControls & SC_TitleBarNormalButton) && + (((titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) && + (titleBar->titleBarState & Qt::WindowMinimized)) || + ((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) && + (titleBar->titleBarState & Qt::WindowMaximized)))) { + QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget); + if (normalButtonRect.isValid()) { + + bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken); + QRect normalButtonIconRect = normalButtonRect.adjusted(buttonMargin, buttonMargin, -buttonMargin, -buttonMargin); + qt_fusion_draw_mdibutton(painter, titleBar, normalButtonRect, hover, sunken); + + QRect frontWindowRect = normalButtonIconRect.adjusted(0, 3, -3, 0); + painter->setPen(textColor); + painter->drawRect(frontWindowRect.adjusted(0, 0, -1, -1)); + painter->drawLine(frontWindowRect.left() + 1, frontWindowRect.top() + 1, + frontWindowRect.right() - 1, frontWindowRect.top() + 1); + painter->setPen(textAlphaColor); + const QPoint points[4] = { + frontWindowRect.topLeft(), + frontWindowRect.topRight(), + frontWindowRect.bottomLeft(), + frontWindowRect.bottomRight() + }; + painter->drawPoints(points, 4); + + QRect backWindowRect = normalButtonIconRect.adjusted(3, 0, 0, -3); + QRegion clipRegion = backWindowRect; + clipRegion -= frontWindowRect; + painter->save(); + painter->setClipRegion(clipRegion); + painter->setPen(textColor); + painter->drawRect(backWindowRect.adjusted(0, 0, -1, -1)); + painter->drawLine(backWindowRect.left() + 1, backWindowRect.top() + 1, + backWindowRect.right() - 1, backWindowRect.top() + 1); + painter->setPen(textAlphaColor); + const QPoint points2[4] = { + backWindowRect.topLeft(), + backWindowRect.topRight(), + backWindowRect.bottomLeft(), + backWindowRect.bottomRight() + }; + painter->drawPoints(points2, 4); + painter->restore(); + } + } + + // context help button + if (titleBar->subControls & SC_TitleBarContextHelpButton + && (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) { + QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget); + if (contextHelpButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken); + qt_fusion_draw_mdibutton(painter, titleBar, contextHelpButtonRect, hover, sunken); + QImage image(qt_titlebar_context_help); + QColor alpha = textColor; + alpha.setAlpha(128); + image.setColor(1, textColor.rgba()); + image.setColor(2, alpha.rgba()); + painter->setRenderHint(QPainter::SmoothPixmapTransform); + painter->drawImage(contextHelpButtonRect.adjusted(4, 4, -4, -4), image); + } + } + + // shade button + if (titleBar->subControls & SC_TitleBarShadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) { + QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget); + if (shadeButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken); + qt_fusion_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken); + QPixmap arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), textColor); + painter->drawPixmap(shadeButtonRect.adjusted(5, 7, -5, -7), arrow); + } + } + + // unshade button + if (titleBar->subControls & SC_TitleBarUnshadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) { + QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget); + if (unshadeButtonRect.isValid()) { + bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver); + bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken); + qt_fusion_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken); + QPixmap arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), textColor, 180); + painter->drawPixmap(unshadeButtonRect.adjusted(5, 7, -5, -7), arrow); + } + } + + if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) { + QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget); + if (iconRect.isValid()) { + if (!titleBar->icon.isNull()) { + titleBar->icon.paint(painter, iconRect); + } else { + QStyleOption tool(0); + tool.palette = titleBar->palette; + QPixmap pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16); + tool.rect = iconRect; + painter->save(); + proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm); + painter->restore(); + } + } + } + } + painter->restore(); + break; + case CC_ScrollBar: + painter->save(); + if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { + bool horizontal = scrollBar->orientation == Qt::Horizontal; + bool sunken = scrollBar->state & State_Sunken; + + QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget); + QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget); + QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget); + QRect scrollBarGroove = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget); + + QRect rect = option->rect; + QColor alphaOutline = outline; + alphaOutline.setAlpha(180); + + QColor arrowColor = option->palette.foreground().color(); + arrowColor.setAlpha(220); + + // Paint groove + if (scrollBar->subControls & SC_ScrollBarGroove) { + QLinearGradient gradient(rect.center().x(), rect.top(), + rect.center().x(), rect.bottom()); + if (!horizontal) + gradient = QLinearGradient(rect.left(), rect.center().y(), + rect.right(), rect.center().y()); + gradient.setColorAt(0, buttonColor.darker(107)); + gradient.setColorAt(0.1, buttonColor.darker(105)); + gradient.setColorAt(0.9, buttonColor.darker(105)); + gradient.setColorAt(1, buttonColor.darker(107)); + + painter->fillRect(option->rect, gradient); + painter->setPen(Qt::NoPen); + painter->setPen(alphaOutline); + if (horizontal) + painter->drawLine(rect.topLeft(), rect.topRight()); + else + painter->drawLine(rect.topLeft(), rect.bottomLeft()); + + QColor subtleEdge = alphaOutline; + subtleEdge.setAlpha(40); + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::NoBrush); + painter->save(); + painter->setClipRect(scrollBarGroove.adjusted(1, 0, -1, -3)); + painter->drawRect(scrollBarGroove.adjusted(1, 0, -1, -1)); + painter->restore(); + } + + QRect pixmapRect = scrollBarSlider; + QLinearGradient gradient(pixmapRect.center().x(), pixmapRect.top(), + pixmapRect.center().x(), pixmapRect.bottom()); + if (!horizontal) + gradient = QLinearGradient(pixmapRect.left(), pixmapRect.center().y(), + pixmapRect.right(), pixmapRect.center().y()); + + QLinearGradient highlightedGradient = gradient; + + QColor midColor2 = mergedColors(gradientStartColor, gradientStopColor, 40); + gradient.setColorAt(0, d->buttonColor(option->palette).lighter(108)); + gradient.setColorAt(1, d->buttonColor(option->palette)); + + highlightedGradient.setColorAt(0, gradientStartColor.darker(102)); + highlightedGradient.setColorAt(1, gradientStopColor.lighter(102)); + + // Paint slider + if (scrollBar->subControls & SC_ScrollBarSlider) { + QRect pixmapRect = scrollBarSlider; + painter->setPen(QPen(alphaOutline, 0)); + if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider) + painter->setBrush(midColor2); + else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider) + painter->setBrush(highlightedGradient); + else + painter->setBrush(gradient); + + painter->drawRect(pixmapRect.adjusted(horizontal ? -1 : 0, horizontal ? 0 : -1, horizontal ? 0 : 1, horizontal ? 1 : 0)); + + painter->setPen(d->innerContrastLine()); + painter->drawRect(scrollBarSlider.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, -1, -1)); + + // Outer shadow + // painter->setPen(subtleEdge); + // if (horizontal) { + //// painter->drawLine(scrollBarSlider.topLeft() + QPoint(-2, 0), scrollBarSlider.bottomLeft() + QPoint(2, 0)); + //// painter->drawLine(scrollBarSlider.topRight() + QPoint(-2, 0), scrollBarSlider.bottomRight() + QPoint(2, 0)); + // } else { + //// painter->drawLine(pixmapRect.topLeft() + QPoint(0, -2), pixmapRect.bottomLeft() + QPoint(0, -2)); + //// painter->drawLine(pixmapRect.topRight() + QPoint(0, 2), pixmapRect.bottomRight() + QPoint(0, 2)); + // } + } + + // The SubLine (up/left) buttons + if (scrollBar->subControls & SC_ScrollBarSubLine) { + if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken) + painter->setBrush(gradientStopColor); + else if ((scrollBar->activeSubControls & SC_ScrollBarSubLine)) + painter->setBrush(highlightedGradient); + else + painter->setBrush(gradient); + + painter->setPen(Qt::NoPen); + painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0)); + painter->setPen(QPen(alphaOutline, 1)); + if (option->state & State_Horizontal) { + if (option->direction == Qt::RightToLeft) { + pixmapRect.setLeft(scrollBarSubLine.left()); + painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft()); + } else { + pixmapRect.setRight(scrollBarSubLine.right()); + painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight()); + } + } else { + pixmapRect.setBottom(scrollBarSubLine.bottom()); + painter->drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight()); + } + + painter->setBrush(Qt::NoBrush); + painter->setPen(d->innerContrastLine()); + painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0 , horizontal ? -2 : -1, horizontal ? -1 : -2)); + + // Arrows + int rotation = 0; + if (option->state & State_Horizontal) + rotation = option->direction == Qt::LeftToRight ? -90 : 90; + QRect upRect = scrollBarSubLine.translated(horizontal ? -2 : -1, 0); + QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation); + painter->drawPixmap(QRect(upRect.center().x() - arrowPixmap.width() / 4 + 2, + upRect.center().y() - arrowPixmap.height() / 4 + 1, + arrowPixmap.width()/2, arrowPixmap.height()/2), arrowPixmap); + } + + // The AddLine (down/right) button + if (scrollBar->subControls & SC_ScrollBarAddLine) { + if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken) + painter->setBrush(gradientStopColor); + else if ((scrollBar->activeSubControls & SC_ScrollBarAddLine)) + painter->setBrush(midColor2); + else + painter->setBrush(gradient); + + painter->setPen(Qt::NoPen); + painter->drawRect(scrollBarAddLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0)); + painter->setPen(QPen(alphaOutline, 1)); + if (option->state & State_Horizontal) { + if (option->direction == Qt::LeftToRight) { + pixmapRect.setLeft(scrollBarAddLine.left()); + painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft()); + } else { + pixmapRect.setRight(scrollBarAddLine.right()); + painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight()); + } + } else { + pixmapRect.setTop(scrollBarAddLine.top()); + painter->drawLine(pixmapRect.topLeft(), pixmapRect.topRight()); + } + + painter->setPen(d->innerContrastLine()); + painter->setBrush(Qt::NoBrush); + painter->drawRect(scrollBarAddLine.adjusted(1, 1, -1, -1)); + + int rotation = 180; + if (option->state & State_Horizontal) + rotation = option->direction == Qt::LeftToRight ? 90 : -90; + QRect downRect = scrollBarAddLine.translated(-1, 1); + QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation); + painter->drawPixmap(QRect(downRect.center().x() - arrowPixmap.width() / 4 + 2, + downRect.center().y() - arrowPixmap.height() / 4, + arrowPixmap.width()/2, arrowPixmap.height()/2), arrowPixmap); + } + + } + painter->restore(); + break;; + case CC_ComboBox: + painter->save(); + if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { + bool hasFocus = option->state & State_HasFocus && option->state & State_KeyboardFocusChange; + bool sunken = comboBox->state & State_On; // play dead, if combobox has no items + bool isEnabled = (comboBox->state & State_Enabled); + QPixmap cache; + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size()); + if (sunken) + pixmapName += QLatin1String("-sunken"); + if (comboBox->editable) + pixmapName += QLatin1String("-editable"); + if (isEnabled) + pixmapName += QLatin1String("-enabled"); + + if (!QPixmapCache::find(pixmapName, cache)) { + cache = styleCachePixmap(comboBox->rect.size()); + cache.fill(Qt::transparent); + QPainter cachePainter(&cache); + QRect pixmapRect(0, 0, comboBox->rect.width(), comboBox->rect.height()); + QStyleOptionComboBox comboBoxCopy = *comboBox; + comboBoxCopy.rect = pixmapRect; + + QRect rect = pixmapRect; + QRect downArrowRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, + SC_ComboBoxArrow, widget); + // Draw a line edit + if (comboBox->editable) { + QStyleOptionFrame buttonOption; + buttonOption.QStyleOption::operator=(*comboBox); + buttonOption.rect = rect; + buttonOption.state = (comboBox->state & (State_Enabled | State_MouseOver | State_HasFocus)) + | State_KeyboardFocusChange; // Allways show hig + + if (sunken) { + buttonOption.state |= State_Sunken; + buttonOption.state &= ~State_MouseOver; + } + + proxy()->drawPrimitive(PE_FrameLineEdit, &buttonOption, &cachePainter, widget); + + // Draw button clipped + cachePainter.save(); + cachePainter.setClipRect(downArrowRect.adjusted(0, 0, 1, 0)); + buttonOption.rect.setLeft(comboBox->direction == Qt::LeftToRight ? + downArrowRect.left() - 6: downArrowRect.right() + 6); + proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget); + cachePainter.restore(); + cachePainter.setPen( QPen(hasFocus ? option->palette.highlight() : outline.lighter(110), 0)); + + if (!sunken) { + int borderSize = 1; + if (comboBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(QPoint(downArrowRect.right() - 1, downArrowRect.top() + borderSize ), + QPoint(downArrowRect.right() - 1, downArrowRect.bottom() - borderSize)); + } else { + cachePainter.drawLine(QPoint(downArrowRect.left() , downArrowRect.top() + borderSize), + QPoint(downArrowRect.left() , downArrowRect.bottom() - borderSize)); + } + } else { + if (comboBox->direction == Qt::RightToLeft) { + cachePainter.drawLine(QPoint(downArrowRect.right(), downArrowRect.top() + 2), + QPoint(downArrowRect.right(), downArrowRect.bottom() - 2)); + + } else { + cachePainter.drawLine(QPoint(downArrowRect.left(), downArrowRect.top() + 2), + QPoint(downArrowRect.left(), downArrowRect.bottom() - 2)); + } + } + } else { + QStyleOptionButton buttonOption; + buttonOption.QStyleOption::operator=(*comboBox); + buttonOption.rect = rect; + buttonOption.state = comboBox->state & (State_Enabled | State_MouseOver | State_HasFocus | State_KeyboardFocusChange); + if (sunken) { + buttonOption.state |= State_Sunken; + buttonOption.state &= ~State_MouseOver; + } + proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget); + } + if (comboBox->subControls & SC_ComboBoxArrow) { + // Draw the up/down arrow + QColor arrowColor = option->palette.buttonText().color(); + arrowColor.setAlpha(220); + QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180); + cachePainter.drawPixmap(QRect(downArrowRect.center().x() - downArrow.width() / 4 + 1, + downArrowRect.center().y() - downArrow.height() / 4 + 1, + downArrow.width()/2, downArrow.height()/2), downArrow); + } + cachePainter.end(); + QPixmapCache::insert(pixmapName, cache); + } + painter->drawPixmap(comboBox->rect.topLeft(), cache); + } + painter->restore(); + break; + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { + QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); + QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); + + bool horizontal = slider->orientation == Qt::Horizontal; + bool ticksAbove = slider->tickPosition & QSlider::TicksAbove; + bool ticksBelow = slider->tickPosition & QSlider::TicksBelow; + QColor activeHighlight = option->palette.color(QPalette::Normal, QPalette::Highlight); + QPixmap cache; + QBrush oldBrush = painter->brush(); + QPen oldPen = painter->pen(); + QColor shadowAlpha(Qt::black); + shadowAlpha.setAlpha(10); + if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) + outline = d->highlightedOutline(option->palette); + + + if ((option->subControls & SC_SliderGroove) && groove.isValid()) { + QColor grooveColor; + grooveColor.setHsv(buttonColor.hue(), + qMin(255, (int)(buttonColor.saturation())), + qMin(255, (int)(buttonColor.value()*0.9))); + QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size()); + QRect pixmapRect(0, 0, groove.width(), groove.height()); + + // draw background groove + if (!QPixmapCache::find(groovePixmapName, cache)) { + cache = styleCachePixmap(pixmapRect.size()); + cache.fill(Qt::transparent); + QPainter groovePainter(&cache); + groovePainter.setRenderHint(QPainter::Antialiasing, true); + groovePainter.translate(0.5, 0.5); + QLinearGradient gradient; + if (horizontal) { + gradient.setStart(pixmapRect.center().x(), pixmapRect.top()); + gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom()); + } + else { + gradient.setStart(pixmapRect.left(), pixmapRect.center().y()); + gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y()); + } + groovePainter.setPen(QPen(outline, 0)); + gradient.setColorAt(0, grooveColor.darker(110)); + gradient.setColorAt(1, grooveColor.lighter(110));//palette.button().color().darker(115)); + groovePainter.setBrush(gradient); + groovePainter.drawRoundedRect(pixmapRect.adjusted(1, 1, -2, -2), 1, 1); + groovePainter.end(); + QPixmapCache::insert(groovePixmapName, cache); + } + painter->drawPixmap(groove.topLeft(), cache); + + // draw blue groove highlight + QRect clipRect; + groovePixmapName += QLatin1String("_blue"); + if (!QPixmapCache::find(groovePixmapName, cache)) { + cache = styleCachePixmap(pixmapRect.size()); + cache.fill(Qt::transparent); + QPainter groovePainter(&cache); + QLinearGradient gradient; + if (horizontal) { + gradient.setStart(pixmapRect.center().x(), pixmapRect.top()); + gradient.setFinalStop(pixmapRect.center().x(), pixmapRect.bottom()); + } + else { + gradient.setStart(pixmapRect.left(), pixmapRect.center().y()); + gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y()); + } + QColor highlight = d->highlight(option->palette); + QColor highlightedoutline = highlight.darker(140); + if (qGray(outline.rgb()) > qGray(highlightedoutline.rgb())) + outline = highlightedoutline; + + + groovePainter.setRenderHint(QPainter::Antialiasing, true); + groovePainter.translate(0.5, 0.5); + groovePainter.setPen(QPen(outline, 0)); + gradient.setColorAt(0, activeHighlight); + gradient.setColorAt(1, activeHighlight.lighter(130)); + groovePainter.setBrush(gradient); + groovePainter.drawRoundedRect(pixmapRect.adjusted(1, 1, -2, -2), 1, 1); + groovePainter.setPen(d->innerContrastLine()); + groovePainter.setBrush(Qt::NoBrush); + groovePainter.drawRoundedRect(pixmapRect.adjusted(2, 2, -3, -3), 1, 1); + groovePainter.end(); + QPixmapCache::insert(groovePixmapName, cache); + } + if (horizontal) { + if (slider->upsideDown) + clipRect = QRect(handle.right(), groove.top(), groove.right() - handle.right(), groove.height()); + else + clipRect = QRect(groove.left(), groove.top(), handle.left(), groove.height()); + } else { + if (slider->upsideDown) + clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - handle.bottom()); + else + clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top()); + } + painter->save(); + painter->setClipRect(clipRect.adjusted(0, 0, 1, 1)); + painter->drawPixmap(groove.topLeft(), cache); + painter->restore(); + } + + // draw handle + if ((option->subControls & SC_SliderHandle) ) { + QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size()); + if (!QPixmapCache::find(handlePixmapName, cache)) { + cache = styleCachePixmap(handle.size()); + cache.fill(Qt::transparent); + QRect pixmapRect(0, 0, handle.width(), handle.height()); + QPainter handlePainter(&cache); + QRect gradRect = pixmapRect.adjusted(2, 2, -2, -2); + + // gradient fill + QRect r = pixmapRect.adjusted(1, 1, -2, -2); + QLinearGradient gradient = qt_fusion_gradient(gradRect, d->buttonColor(option->palette),horizontal ? TopDown : FromLeft); + + handlePainter.setRenderHint(QPainter::Antialiasing, true); + handlePainter.translate(0.5, 0.5); + + handlePainter.setPen(Qt::NoPen); + handlePainter.setBrush(QColor(0, 0, 0, 40)); + handlePainter.drawRect(r.adjusted(-1, 2, 1, -2)); + + handlePainter.setPen(QPen(d->outline(option->palette), 1)); + if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange) + handlePainter.setPen(QPen(d->highlightedOutline(option->palette), 1)); + + handlePainter.setBrush(gradient); + handlePainter.drawRoundedRect(r, 2, 2); + handlePainter.setBrush(Qt::NoBrush); + handlePainter.setPen(d->innerContrastLine()); + handlePainter.drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2); + + QColor cornerAlpha = outline.darker(120); + cornerAlpha.setAlpha(80); + + //handle shadow + handlePainter.setPen(shadowAlpha); + handlePainter.drawLine(QPoint(r.left() + 2, r.bottom() + 1), QPoint(r.right() - 2, r.bottom() + 1)); + handlePainter.drawLine(QPoint(r.right() + 1, r.bottom() - 3), QPoint(r.right() + 1, r.top() + 4)); + handlePainter.drawLine(QPoint(r.right() - 1, r.bottom()), QPoint(r.right() + 1, r.bottom() - 2)); + + handlePainter.end(); + QPixmapCache::insert(handlePixmapName, cache); + } + + painter->drawPixmap(handle.topLeft(), cache); + + } + if (option->subControls & SC_SliderTickmarks) { + painter->setPen(outline); + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget); + int interval = slider->tickInterval; + if (interval <= 0) { + interval = slider->singleStep; + if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval, + available) + - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, + 0, available) < 3) + interval = slider->pageStep; + } + if (interval <= 0) + interval = 1; + + int v = slider->minimum; + int len = proxy()->pixelMetric(PM_SliderLength, slider, widget); + while (v <= slider->maximum + 1) { + if (v == slider->maximum + 1 && interval == 1) + break; + const int v_ = qMin(v, slider->maximum); + int pos = sliderPositionFromValue(slider->minimum, slider->maximum, + v_, (horizontal + ? slider->rect.width() + : slider->rect.height()) - len, + slider->upsideDown) + len / 2; + int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0); + + if (horizontal) { + if (ticksAbove) { + painter->drawLine(pos, slider->rect.top() + extra, + pos, slider->rect.top() + tickSize); + } + if (ticksBelow) { + painter->drawLine(pos, slider->rect.bottom() - extra, + pos, slider->rect.bottom() - tickSize); + } + } else { + if (ticksAbove) { + painter->drawLine(slider->rect.left() + extra, pos, + slider->rect.left() + tickSize, pos); + } + if (ticksBelow) { + painter->drawLine(slider->rect.right() - extra, pos, + slider->rect.right() - tickSize, pos); + } + } + // in the case where maximum is max int + int nextInterval = v + interval; + if (nextInterval < v) + break; + v = nextInterval; + } + } + painter->setBrush(oldBrush); + painter->setPen(oldPen); + } + break; + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option)) + QStyleHelper::drawDial(dial, painter); + break; + default: + QCommonStyle::drawComplexControl(control, option, painter, widget); + break; + } +} + +/*! + \reimp +*/ +int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + switch (metric) { + case PM_HeaderMargin: + return 2; + case PM_ToolTipLabelFrameWidth: + return 2; + case PM_ButtonDefaultIndicator: + return 0; + case PM_ButtonShiftHorizontal: + case PM_ButtonShiftVertical: + return 0; + case PM_MessageBoxIconSize: + return 48; + case PM_ListViewIconSize: + return 24; + case PM_DialogButtonsSeparator: + case PM_ScrollBarSliderMin: + return 26; + case PM_TitleBarHeight: + return 24; + case PM_ScrollBarExtent: + return 14; + case PM_SliderThickness: + return 15; + case PM_SliderLength: + return 15; + case PM_DockWidgetTitleMargin: + return 1; + case PM_DefaultFrameWidth: + return 1; + case PM_SpinBoxFrameWidth: + return 3; + case PM_MenuVMargin: + case PM_MenuHMargin: + return 0; + case PM_MenuPanelWidth: + return 0; + case PM_MenuBarItemSpacing: + return 6; + case PM_MenuBarVMargin: + return 0; + case PM_MenuBarHMargin: + return 0; + case PM_MenuBarPanelWidth: + return 0; + case PM_ToolBarHandleExtent: + return 9; + case PM_ToolBarItemSpacing: + return 1; + case PM_ToolBarFrameWidth: + return 2; + case PM_ToolBarItemMargin: + return 2; + case PM_SmallIconSize: + return 16; + case PM_ButtonIconSize: + return 16; + case PM_DockWidgetTitleBarButtonMargin: + return 2; + case PM_MaximumDragDistance: + return -1; + case PM_TabCloseIndicatorWidth: + case PM_TabCloseIndicatorHeight: + return 20; + case PM_TabBarTabVSpace: + return 12; + case PM_TabBarTabOverlap: + return 1; + case PM_TabBarBaseOverlap: + return 2; + case PM_SubMenuOverlap: + return -1; + case PM_DockWidgetHandleExtent: + case PM_SplitterWidth: + return 4; + case PM_IndicatorHeight: + case PM_IndicatorWidth: + case PM_ExclusiveIndicatorHeight: + case PM_ExclusiveIndicatorWidth: + return 14; + case PM_ScrollView_ScrollBarSpacing: + return 0; + default: + break; + } + return QCommonStyle::pixelMetric(metric, option, widget); +} + +/*! + \reimp +*/ +QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const +{ + QSize newSize = QCommonStyle::sizeFromContents(type, option, size, widget); + switch (type) { + case CT_PushButton: + if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { + if (!btn->text.isEmpty() && newSize.width() < 80) + newSize.setWidth(80); + if (!btn->icon.isNull() && btn->iconSize.height() > 16) + newSize -= QSize(0, 2); + } + break; + case CT_GroupBox: + newSize += QSize(10, 10); // Add some space below the groupbox + break; + case CT_RadioButton: + case CT_CheckBox: + newSize += QSize(0, 1); + break; + case CT_ToolButton: + newSize += QSize(2, 2); + break; + case CT_SpinBox: + newSize += QSize(0, -2); + break; + case CT_ComboBox: + newSize += QSize(2, 4); + break; + case CT_LineEdit: + newSize += QSize(0, 4); + break; + case CT_MenuBarItem: + newSize += QSize(8, 5); + break; + case CT_MenuItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { + int w = newSize.width(); + int maxpmw = menuItem->maxIconWidth; + int tabSpacing = 20; + if (menuItem->text.contains(QLatin1Char('\t'))) + w += tabSpacing; + else if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) + w += 2 * QFusionStylePrivate::menuArrowHMargin; + else if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) { + QFontMetrics fm(menuItem->font); + QFont fontBold = menuItem->font; + fontBold.setBold(true); + QFontMetrics fmBold(fontBold); + w += fmBold.width(menuItem->text) - fm.width(menuItem->text); + } + int checkcol = qMax<int>(maxpmw, QFusionStylePrivate::menuCheckMarkWidth); // Windows always shows a check column + w += checkcol; + w += int(QFusionStylePrivate::menuRightBorder) + 10; + newSize.setWidth(w); + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + if (!menuItem->text.isEmpty()) { + newSize.setHeight(menuItem->fontMetrics.height()); + } + } + else if (!menuItem->icon.isNull()) { + if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget)) { + newSize.setHeight(qMax(combo->iconSize().height() + 2, newSize.height())); + } + } + newSize.setWidth(newSize.width() + 12); + newSize.setWidth(qMax(newSize.width(), 120)); + } + break; + case CT_SizeGrip: + newSize += QSize(4, 4); + break; + case CT_MdiControls: + if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(option)) { + int width = 0; + if (styleOpt->subControls & SC_MdiMinButton) + width += 19 + 1; + if (styleOpt->subControls & SC_MdiNormalButton) + width += 19 + 1; + if (styleOpt->subControls & SC_MdiCloseButton) + width += 19 + 1; + newSize = QSize(width, 19); + } else { + newSize = QSize(60, 19); + } + break; + default: + break; + } + return newSize; +} + +/*! + \reimp +*/ +void QFusionStyle::polish(QApplication *app) +{ + QCommonStyle::polish(app); +} + +/*! + \reimp +*/ +void QFusionStyle::polish(QWidget *widget) +{ + QCommonStyle::polish(widget); + if (qobject_cast<QAbstractButton*>(widget) + || qobject_cast<QComboBox *>(widget) + || qobject_cast<QProgressBar *>(widget) + || qobject_cast<QScrollBar *>(widget) + || qobject_cast<QSplitterHandle *>(widget) + || qobject_cast<QAbstractSlider *>(widget) + || qobject_cast<QAbstractSpinBox *>(widget) + || (widget->inherits("QDockSeparator")) + || (widget->inherits("QDockWidgetSeparator")) + ) { + widget->setAttribute(Qt::WA_Hover, true); + } +} + +/*! + \reimp +*/ +void QFusionStyle::polish(QPalette &pal) +{ + QCommonStyle::polish(pal); +} + +/*! + \reimp +*/ +void QFusionStyle::unpolish(QWidget *widget) +{ + QCommonStyle::unpolish(widget); + if (qobject_cast<QAbstractButton*>(widget) + || qobject_cast<QComboBox *>(widget) + || qobject_cast<QProgressBar *>(widget) + || qobject_cast<QScrollBar *>(widget) + || qobject_cast<QSplitterHandle *>(widget) + || qobject_cast<QAbstractSlider *>(widget) + || qobject_cast<QAbstractSpinBox *>(widget) + || (widget->inherits("QDockSeparator")) + || (widget->inherits("QDockWidgetSeparator")) + ) { + widget->setAttribute(Qt::WA_Hover, false); + } +} + +/*! + \reimp +*/ +void QFusionStyle::unpolish(QApplication *app) +{ + QCommonStyle::unpolish(app); +} + +/*! + \reimp +*/ +QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, + SubControl subControl, const QWidget *widget) const +{ + QRect rect = QCommonStyle::subControlRect(control, option, subControl, widget); + + switch (control) { + case CC_Slider: + if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { + int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget); + switch (subControl) { + case SC_SliderHandle: { + if (slider->orientation == Qt::Horizontal) { + rect.setHeight(proxy()->pixelMetric(PM_SliderThickness)); + rect.setWidth(proxy()->pixelMetric(PM_SliderLength)); + int centerY = slider->rect.center().y() - rect.height() / 2; + if (slider->tickPosition & QSlider::TicksAbove) + centerY += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerY -= tickSize; + rect.moveTop(centerY); + } else { + rect.setWidth(proxy()->pixelMetric(PM_SliderThickness)); + rect.setHeight(proxy()->pixelMetric(PM_SliderLength)); + int centerX = slider->rect.center().x() - rect.width() / 2; + if (slider->tickPosition & QSlider::TicksAbove) + centerX += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + centerX -= tickSize; + rect.moveLeft(centerX); + } + } + break; + case SC_SliderGroove: { + QPoint grooveCenter = slider->rect.center(); + if (slider->orientation == Qt::Horizontal) { + rect.setHeight(7); + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.ry() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.ry() -= tickSize; + } else { + rect.setWidth(7); + if (slider->tickPosition & QSlider::TicksAbove) + grooveCenter.rx() += tickSize; + if (slider->tickPosition & QSlider::TicksBelow) + grooveCenter.rx() -= tickSize; + } + rect.moveCenter(grooveCenter); + break; + } + default: + break; + } + } + break; + case CC_SpinBox: + if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + QSize bs; + int center = spinbox->rect.height() / 2; + int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0; + int y = fw; + bs.setHeight(qMax(8, spinbox->rect.height()/2 - y)); + bs.setWidth(14); + int x, lx, rx; + x = spinbox->rect.width() - y - bs.width() + 2; + lx = fw; + rx = x - fw; + switch (subControl) { + case SC_SpinBoxUp: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + rect = QRect(x, fw, bs.width(), center - fw); + break; + case SC_SpinBoxDown: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) + return QRect(); + + rect = QRect(x, center, bs.width(), spinbox->rect.bottom() - center - fw + 1); + break; + case SC_SpinBoxEditField: + if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) { + rect = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw); + } else { + rect = QRect(lx, fw, rx - qMax(fw - 1, 0), spinbox->rect.height() - 2*fw); + } + break; + case SC_SpinBoxFrame: + rect = spinbox->rect; + default: + break; + } + rect = visualRect(spinbox->direction, spinbox->rect, rect); + } + break; + + case CC_GroupBox: + if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) { + rect = option->rect; + if (subControl == SC_GroupBoxFrame) + return rect.adjusted(0, 0, 0, 0); + else if (subControl == SC_GroupBoxContents) { + QRect frameRect = option->rect.adjusted(0, 0, 0, -groupBoxBottomMargin); + int margin = 3; + int leftMarginExtension = 0; + return frameRect.adjusted(leftMarginExtension + margin, margin + groupBoxTopMargin + groupBoxTitleMargin, -margin, -margin - groupBoxBottomMargin); + } + + QSize textSize = option->fontMetrics.boundingRect(groupBox->text).size() + QSize(4, 4); + int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget); + int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget); + rect = QRect(); + if (subControl == SC_GroupBoxCheckBox) { + rect.setWidth(indicatorWidth); + rect.setHeight(indicatorHeight); + rect.moveTop((textSize.height() - indicatorHeight - 5) / 2); + rect.moveLeft(1); + } else if (subControl == SC_GroupBoxLabel) { + rect.setSize(textSize); + rect.moveTop(0); + if (option->subControls & QStyle::SC_GroupBoxCheckBox) + rect.translate(indicatorWidth + 5, 0); + } + return visualRect(option->direction, option->rect, rect); + } + + return rect; + + case CC_ComboBox: + switch (subControl) { + case SC_ComboBoxArrow: + rect = visualRect(option->direction, option->rect, rect); + rect.setRect(rect.right() - 18, rect.top() - 2, + 19, rect.height() + 4); + rect = visualRect(option->direction, option->rect, rect); + break; + case SC_ComboBoxEditField: { + int frameWidth = 2; + rect = visualRect(option->direction, option->rect, rect); + rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth, + option->rect.width() - 19 - 2 * frameWidth, + option->rect.height() - 2 * frameWidth); + if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { + if (!box->editable) { + rect.adjust(2, 0, 0, 0); + if (box->state & (State_Sunken | State_On)) + rect.translate(1, 1); + } + } + rect = visualRect(option->direction, option->rect, rect); + break; + } + default: + break; + } + break; + case CC_TitleBar: + if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) { + SubControl sc = subControl; + QRect &ret = rect; + const int indent = 3; + const int controlTopMargin = 3; + const int controlBottomMargin = 3; + const int controlWidthMargin = 2; + const int controlHeight = tb->rect.height() - controlTopMargin - controlBottomMargin ; + const int delta = controlHeight + controlWidthMargin; + int offset = 0; + + bool isMinimized = tb->titleBarState & Qt::WindowMinimized; + bool isMaximized = tb->titleBarState & Qt::WindowMaximized; + + switch (sc) { + case SC_TitleBarLabel: + if (tb->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) { + ret = tb->rect; + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + ret.adjust(delta, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowShadeButtonHint) + ret.adjust(0, 0, -delta, 0); + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + ret.adjust(0, 0, -delta, 0); + } + break; + case SC_TitleBarContextHelpButton: + if (tb->titleBarFlags & Qt::WindowContextHelpButtonHint) + offset += delta; + case SC_TitleBarMinButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMinButton) + break; + case SC_TitleBarNormalButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) + offset += delta; + else if (isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarNormalButton) + break; + case SC_TitleBarMaxButton: + if (!isMaximized && (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarMaxButton) + break; + case SC_TitleBarShadeButton: + if (!isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarShadeButton) + break; + case SC_TitleBarUnshadeButton: + if (isMinimized && (tb->titleBarFlags & Qt::WindowShadeButtonHint)) + offset += delta; + else if (sc == SC_TitleBarUnshadeButton) + break; + case SC_TitleBarCloseButton: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) + offset += delta; + else if (sc == SC_TitleBarCloseButton) + break; + ret.setRect(tb->rect.right() - indent - offset, tb->rect.top() + controlTopMargin, + controlHeight, controlHeight); + break; + case SC_TitleBarSysMenu: + if (tb->titleBarFlags & Qt::WindowSystemMenuHint) { + ret.setRect(tb->rect.left() + controlWidthMargin + indent, tb->rect.top() + controlTopMargin, + controlHeight, controlHeight); + } + break; + default: + break; + } + ret = visualRect(tb->direction, tb->rect, ret); + } + break; + default: + break; + } + + return rect; +} + + +/*! + \reimp +*/ +QRect QFusionStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const +{ + return QCommonStyle::itemPixmapRect(r, flags, pixmap); +} + +/*! + \reimp +*/ +void QFusionStyle::drawItemPixmap(QPainter *painter, const QRect &rect, + int alignment, const QPixmap &pixmap) const +{ + QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap); +} + +/*! + \reimp +*/ +QStyle::SubControl QFusionStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w) const +{ + return QCommonStyle::hitTestComplexControl(cc, opt, pt, w); +} + +/*! + \reimp +*/ +QPixmap QFusionStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const +{ + return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt); +} + +/*! + \reimp +*/ +int QFusionStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, + QStyleHintReturn *returnData) const +{ + switch (hint) { + case SH_Slider_SnapToValue: + case SH_PrintDialog_RightAlignButtons: + case SH_FontDialog_SelectAssociatedText: + case SH_MenuBar_AltKeyNavigation: + case SH_ComboBox_ListMouseTracking: + case SH_ScrollBar_StopMouseOverSlider: + case SH_ScrollBar_MiddleClickAbsolutePosition: + case SH_EtchDisabledText: + case SH_TitleBar_AutoRaise: + case SH_TitleBar_NoBorder: + case SH_ItemView_ShowDecorationSelected: + case SH_ItemView_ArrowKeysNavigateIntoChildren: + case SH_ItemView_ChangeHighlightOnFocus: + case SH_MenuBar_MouseTracking: + case SH_Menu_MouseTracking: + return 1; + + case SH_ToolBox_SelectedPageTitleBold: + case SH_ScrollView_FrameOnlyAroundContents: + case SH_Menu_AllowActiveAndDisabled: + case SH_MainWindow_SpaceBelowMenuBar: + case SH_DialogButtonBox_ButtonsHaveIcons: + case SH_MessageBox_CenterButtons: + case SH_RubberBand_Mask: + return 0; + + case SH_ComboBox_Popup: + if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) + return !cmb->editable; + return 0; + + case SH_Table_GridLineColor: + return option->palette.background().color().darker(120).rgb(); + + case SH_MessageBox_TextInteractionFlags: + return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; + + case SH_WizardStyle: + return QWizard::ClassicStyle; + + case SH_Menu_SubMenuPopupDelay: + return 225; // default from GtkMenu + + case SH_WindowFrame_Mask: + if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask *>(returnData)) { + //left rounded corner + mask->region = option->rect; + mask->region -= QRect(option->rect.left(), option->rect.top(), 5, 1); + mask->region -= QRect(option->rect.left(), option->rect.top() + 1, 3, 1); + mask->region -= QRect(option->rect.left(), option->rect.top() + 2, 2, 1); + mask->region -= QRect(option->rect.left(), option->rect.top() + 3, 1, 2); + + //right rounded corner + mask->region -= QRect(option->rect.right() - 4, option->rect.top(), 5, 1); + mask->region -= QRect(option->rect.right() - 2, option->rect.top() + 1, 3, 1); + mask->region -= QRect(option->rect.right() - 1, option->rect.top() + 2, 2, 1); + mask->region -= QRect(option->rect.right() , option->rect.top() + 3, 1, 2); + return 1; + } + default: + break; + } + return QCommonStyle::styleHint(hint, option, widget, returnData); +} + +/*! \reimp */ +QRect QFusionStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidget *w) const +{ + QRect r = QCommonStyle::subElementRect(sr, opt, w); + switch (sr) { + case SE_ProgressBarLabel: + case SE_ProgressBarContents: + case SE_ProgressBarGroove: + return opt->rect; + case SE_PushButtonFocusRect: + r.adjust(0, 1, 0, -1); + break; + case SE_DockWidgetTitleBarText: { + if (const QStyleOptionDockWidget *titlebar = qstyleoption_cast<const QStyleOptionDockWidget*>(opt)) { + bool verticalTitleBar = titlebar->verticalTitleBar; + if (verticalTitleBar) { + r.adjust(0, 0, 0, -4); + } else { + if (opt->direction == Qt::LeftToRight) + r.adjust(4, 0, 0, 0); + else + r.adjust(0, 0, -4, 0); + } + } + + break; + } + default: + break; + } + return r; +} + +/*! + \reimp +*/ +QIcon QFusionStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, + const QWidget *widget) const +{ + return QCommonStyle::standardIcon(standardIcon, option, widget); +} + +/*! + \reimp + */ +QPixmap QFusionStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget) const +{ +#ifndef QT_NO_IMAGEFORMAT_XPM + switch (standardPixmap) { + case SP_TitleBarNormalButton: + return QPixmap((const char **)dock_widget_restore_xpm); + case SP_TitleBarMinButton: + return QPixmap((const char **)workspace_minimize); + case SP_TitleBarCloseButton: + case SP_DockWidgetCloseButton: + return QPixmap((const char **)dock_widget_close_xpm); + + default: + break; + } +#endif //QT_NO_IMAGEFORMAT_XPM + + return QCommonStyle::standardPixmap(standardPixmap, opt, widget); +} + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_FUSION || QT_PLUGIN diff --git a/src/widgets/styles/qfusionstyle.h b/src/widgets/styles/qfusionstyle.h new file mode 100644 index 0000000000..927ba32342 --- /dev/null +++ b/src/widgets/styles/qfusionstyle.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFUSIONSTYLE_H +#define QFUSIONSTYLE_H + +#include <QtWidgets/qcommonstyle.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +#if !defined(QT_NO_STYLE_FUSION) + +class QFusionStylePrivate; +class Q_WIDGETS_EXPORT QFusionStyle : public QCommonStyle +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QFusionStyle) + +public: + QFusionStyle(); + ~QFusionStyle(); + + QPalette standardPalette () const; + void drawPrimitive(PrimitiveElement elem, + const QStyleOption *option, + QPainter *painter, const QWidget *widget = 0) const; + void drawControl(ControlElement ce, const QStyleOption *option, QPainter *painter, + const QWidget *widget) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, + QPainter *painter, const QWidget *widget) const; + QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const; + QSize sizeFromContents(ContentsType type, const QStyleOption *option, + const QSize &size, const QWidget *widget) const; + SubControl hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, + const QPoint &pt, const QWidget *w = 0) const; + QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, + SubControl sc, const QWidget *widget) const; + QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, + const QStyleOption *opt) const; + int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, + QStyleHintReturn *returnData = 0) const; + QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const; + QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = 0, + const QWidget *widget = 0) const; + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, + const QWidget *widget = 0) const; + void drawItemPixmap(QPainter *painter, const QRect &rect, + int alignment, const QPixmap &pixmap) const; + void drawItemText(QPainter *painter, const QRect &rect, + int flags, const QPalette &pal, bool enabled, + const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; + void polish(QWidget *widget); + void polish(QApplication *app); + void polish(QPalette &pal); + void unpolish(QWidget *widget); + void unpolish(QApplication *app); + +protected: + QFusionStyle(QFusionStylePrivate &dd); + +}; + +#endif // QT_NO_STYLE_FUSION + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFUSIONSTYLE_H diff --git a/src/widgets/styles/qfusionstyle_p.h b/src/widgets/styles/qfusionstyle_p.h new file mode 100644 index 0000000000..1c8089e736 --- /dev/null +++ b/src/widgets/styles/qfusionstyle_p.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFUSIONSTYLE_P_H +#define QFUSIONSTYLE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qcommonstyle.h" +#include "qcommonstyle_p.h" + +#ifndef QT_NO_STYLE_FUSION + +QT_BEGIN_NAMESPACE + +class QFusionStylePrivate : public QCommonStylePrivate +{ + Q_DECLARE_PUBLIC(QFusionStyle) + +public: + QFusionStylePrivate(); + + // Used for grip handles + QColor lightShade() const { + return QColor(255, 255, 255, 90); + } + QColor darkShade() const { + return QColor(0, 0, 0, 60); + } + + QColor topShadow() const { + return QColor(0, 0, 0, 18); + } + + QColor innerContrastLine() const { + return QColor(255, 255, 255, 30); + } + + QColor highlight(const QPalette &pal) const { + return pal.color(QPalette::Active, QPalette::Highlight); + } + + QColor outline(const QPalette &pal) const { + if (!pal.window().texture().isNull()) + return QColor(0, 0, 0, 160); + return pal.background().color().darker(140); + } + + QColor highlightedOutline(const QPalette &pal) const { + QColor highlightedOutline = pal.highlight().color().darker(125); + if (highlightedOutline.value() > 160) + highlightedOutline.setHsl(highlightedOutline.hue(), highlightedOutline.saturation(), 160); + return highlightedOutline; + } + + QColor tabFrameColor(const QPalette &pal) const { + if (!pal.button().texture().isNull()) + return QColor(255, 255, 255, 8); + return buttonColor(pal).lighter(104); + } + + QColor buttonColor(const QPalette &pal) const { + QColor buttonColor = pal.button().color(); + int val = qGray(buttonColor.rgb()); + buttonColor = buttonColor.lighter(100 + qMax(0, (180- val)/6)); + buttonColor.setHsv(buttonColor.hue(), buttonColor.saturation() * 0.75, buttonColor.value()); + return buttonColor; + } + + enum { + menuItemHMargin = 3, // menu item hor text margin + menuArrowHMargin = 6, // menu arrow horizontal margin + menuRightBorder = 15, // right border on menus + menuCheckMarkWidth = 12 // checkmarks width on menus + }; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_STYLE_FUSION + +#endif //QFUSIONSTYLE_P_H diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp index 9bcf45e928..e9701f9d6f 100644 --- a/src/widgets/styles/qgtkstyle.cpp +++ b/src/widgets/styles/qgtkstyle.cpp @@ -71,6 +71,7 @@ #include <QtWidgets/QWizard> #include <qpixmapcache.h> +#include <private/qstyleanimation_p.h> #undef signals // Collides with GTK stymbols #include <private/qgtkpainter_p.h> #include <private/qstylehelper_p.h> @@ -266,7 +267,7 @@ static GdkColor fromQColor(const QColor &color) \since 4.5 \inmodule QtWidgets - + The QGtkStyle style provides a look and feel that integrates well into GTK-based desktop environments such as the XFCe and GNOME. @@ -284,7 +285,7 @@ static GdkColor fromQColor(const QColor &color) Constructs a QGtkStyle object. */ QGtkStyle::QGtkStyle() - : QWindowsStyle(*new QGtkStylePrivate) + : QCommonStyle(*new QGtkStylePrivate) { Q_D(QGtkStyle); d->init(); @@ -296,7 +297,7 @@ QGtkStyle::QGtkStyle() Constructs a QGtkStyle object. */ QGtkStyle::QGtkStyle(QGtkStylePrivate &dd) - : QWindowsStyle(dd) + : QCommonStyle(dd) { Q_D(QGtkStyle); d->init(); @@ -317,7 +318,7 @@ QPalette QGtkStyle::standardPalette() const { Q_D(const QGtkStyle); - QPalette palette = QWindowsStyle::standardPalette(); + QPalette palette = QCommonStyle::standardPalette(); if (d->isThemeAvailable()) { GtkStyle *style = d->gtkStyle(); GtkWidget *gtkButton = d->gtkWidget("GtkButton"); @@ -408,7 +409,7 @@ void QGtkStyle::polish(QPalette &palette) Q_D(QGtkStyle); if (!d->isThemeAvailable()) - QWindowsStyle::polish(palette); + QCommonStyle::polish(palette); else palette = palette.resolve(standardPalette()); } @@ -420,8 +421,8 @@ void QGtkStyle::polish(QApplication *app) { Q_D(QGtkStyle); - QWindowsStyle::polish(app); - // Custom fonts and palettes with QtConfig are intentionally + QCommonStyle::polish(app); + // Custom fonts and palettes with QtConfig are intentionally // not supported as these should be entirely determined by // current Gtk settings if (app->desktopSettingsAware() && d->isThemeAvailable()) { @@ -447,7 +448,7 @@ void QGtkStyle::unpolish(QApplication *app) { Q_D(QGtkStyle); - QWindowsStyle::unpolish(app); + QCommonStyle::unpolish(app); QPixmapCache::clear(); if (app->desktopSettingsAware() && d->isThemeAvailable() @@ -470,7 +471,7 @@ void QGtkStyle::polish(QWidget *widget) { Q_D(QGtkStyle); - QWindowsStyle::polish(widget); + QCommonStyle::polish(widget); if (!d->isThemeAvailable()) return; if (qobject_cast<QAbstractButton*>(widget) @@ -494,7 +495,7 @@ void QGtkStyle::polish(QWidget *widget) */ void QGtkStyle::unpolish(QWidget *widget) { - QWindowsStyle::unpolish(widget); + QCommonStyle::unpolish(widget); } /*! @@ -507,7 +508,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric, Q_D(const QGtkStyle); if (!d->isThemeAvailable()) - return QWindowsStyle::pixelMetric(metric, option, widget); + return QCommonStyle::pixelMetric(metric, option, widget); switch (metric) { case PM_DefaultFrameWidth: @@ -692,7 +693,7 @@ int QGtkStyle::pixelMetric(PixelMetric metric, case PM_TabCloseIndicatorHeight: return 20; default: - return QWindowsStyle::pixelMetric(metric, option, widget); + return QCommonStyle::pixelMetric(metric, option, widget); } } @@ -706,17 +707,21 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg Q_D(const QGtkStyle); if (!d->isThemeAvailable()) - return QWindowsStyle::styleHint(hint, option, widget, returnData); + return QCommonStyle::styleHint(hint, option, widget, returnData); switch (hint) { + case SH_ItemView_ChangeHighlightOnFocus: + return true; case SH_ScrollBar_MiddleClickAbsolutePosition: return true; case SH_Menu_AllowActiveAndDisabled: return false; case SH_MainWindow_SpaceBelowMenuBar: - return 0; + return false; case SH_MenuBar_MouseTracking: return true; + case SH_Menu_MouseTracking: + return true; case SH_TitleBar_AutoRaise: return true; case SH_TitleBar_NoBorder: @@ -742,7 +747,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg mask->region -= QRect(option->rect.right() - 1, option->rect.top() + 2, 2, 1); mask->region -= QRect(option->rect.right() , option->rect.top() + 3, 1, 2); } - return QWindowsStyle::styleHint(hint, option, widget, returnData); + return QCommonStyle::styleHint(hint, option, widget, returnData); case SH_MessageBox_TextInteractionFlags: return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse; case SH_MessageBox_CenterButtons: @@ -767,7 +772,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg case SH_ToolButtonStyle: { if (d->isKDE4Session()) - return QWindowsStyle::styleHint(hint, option, widget, returnData); + return QCommonStyle::styleHint(hint, option, widget, returnData); GtkWidget *gtkToolbar = d->gtkWidget("GtkToolbar"); GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS; g_object_get(gtkToolbar, "toolbar-style", &toolbar_style, NULL); @@ -838,7 +843,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg default: break; } - return QWindowsStyle::styleHint(hint, option, widget, returnData); + return QCommonStyle::styleHint(hint, option, widget, returnData); } /*! @@ -852,7 +857,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, Q_D(const QGtkStyle); if (!d->isThemeAvailable()) { - QWindowsStyle::drawPrimitive(element, option, painter, widget); + QCommonStyle::drawPrimitive(element, option, painter, widget); return; } @@ -979,14 +984,11 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, break; case PE_FrameDefaultButton: // fall through - case PE_FrameFocusRect: - if ((widget && qobject_cast<const QAbstractItemView*>(widget))) { - if (option->state & State_KeyboardFocusChange) - QWindowsStyle::drawPrimitive(element, option, painter, widget); - } else { - // ### this mess should move to subcontrolrect - QRect frameRect = option->rect.adjusted(1, 1, -2, -2); - if ( qobject_cast<const QTabBar*>(widget)) { + case PE_FrameFocusRect: { + QRect frameRect = option->rect.adjusted(1, 1, -2, -2); // ### this mess should move to subcontrolrect + if (qobject_cast<const QAbstractItemView*>(widget)) { + // Dont draw anything + } else if (qobject_cast<const QTabBar*>(widget)) { GtkWidget *gtkNotebook = d->gtkWidget("GtkNotebook"); style = gtkPainter.getStyle(gtkNotebook); gtkPainter.paintFocus(gtkNotebook, "tab", frameRect.adjusted(-1, 1, 1, 1), GTK_STATE_ACTIVE, style); @@ -1421,7 +1423,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, case QTabBar::TriangularWest: case QTabBar::TriangularSouth: painter->restore(); - QWindowsStyle::drawPrimitive(element, option, painter, widget); + QCommonStyle::drawPrimitive(element, option, painter, widget); return; } @@ -1435,7 +1437,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, break; default: - QWindowsStyle::drawPrimitive(element, option, painter, widget); + QCommonStyle::drawPrimitive(element, option, painter, widget); } } @@ -1449,7 +1451,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom Q_D(const QGtkStyle); if (!d->isThemeAvailable()) { - QWindowsStyle::drawComplexControl(control, option, painter, widget); + QCommonStyle::drawComplexControl(control, option, painter, widget); return; } @@ -2614,7 +2616,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom #endif // QT_NO_SLIDER default: - QWindowsStyle::drawComplexControl(control, option, painter, widget); + QCommonStyle::drawComplexControl(control, option, painter, widget); break; } @@ -2632,7 +2634,7 @@ void QGtkStyle::drawControl(ControlElement element, Q_D(const QGtkStyle); if (!d->isThemeAvailable()) { - QWindowsStyle::drawControl(element, option, painter, widget); + QCommonStyle::drawControl(element, option, painter, widget); return; } @@ -3061,10 +3063,8 @@ void QGtkStyle::drawControl(ControlElement element, // Draws one item in a popup menu. if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { - const int windowsItemFrame = 2; // menu item frame width const int windowsItemHMargin = 3; // menu item hor text margin const int windowsItemVMargin = 26; // menu item ver text margin - const int windowsRightBorder = 15; // right border on windows GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget("GtkMenu.GtkCheckMenuItem") : d->gtkWidget("GtkMenu.GtkMenuItem"); @@ -3251,9 +3251,9 @@ void QGtkStyle::drawControl(ControlElement element, int x, y, w, h; menuitem->rect.getRect(&x, &y, &w, &h); int tab = menuitem->tabWidth; - int xm = windowsItemFrame + checkcol + windowsItemHMargin; + int xm = QGtkStylePrivate::menuItemFrame + checkcol + windowsItemHMargin; int xpos = menuitem->rect.x() + xm + 1; - QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin); + QRect textRect(xpos, y + windowsItemVMargin, w - xm - QGtkStylePrivate::menuRightBorder - tab + 1, h - 2 * windowsItemVMargin); QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect); QString s = menuitem->text; @@ -3406,7 +3406,7 @@ void QGtkStyle::drawControl(ControlElement element, break; default: - QWindowsStyle::drawControl(element, option, painter, widget); + QCommonStyle::drawControl(element, option, painter, widget); break; } @@ -3487,13 +3487,15 @@ void QGtkStyle::drawControl(ControlElement element, progressBar.setRect(rect.left(), rect.top(), width, rect.height()); else progressBar.setRect(rect.right() - width, rect.top(), width, rect.height()); - + d->stopAnimation(option->styleObject); } else { Q_D(const QGtkStyle); int slideWidth = ((rect.width() - 4) * 2) / 3; - int step = ((d->animateStep * slideWidth) / d->animationFps) % slideWidth; - if ((((d->animateStep * slideWidth) / d->animationFps) % (2 * slideWidth)) >= slideWidth) - step = slideWidth - step; + int step = 0; + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(option->styleObject))) + step = animation->progressStep(slideWidth); + else + d->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject)); progressBar.setRect(rect.left() + step, rect.top(), slideWidth / 2, rect.height()); } @@ -3508,7 +3510,7 @@ void QGtkStyle::drawControl(ControlElement element, break; default: - QWindowsStyle::drawControl(element, option, painter, widget); + QCommonStyle::drawControl(element, option, painter, widget); } } @@ -3520,9 +3522,9 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple { Q_D(const QGtkStyle); - QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget); + QRect rect = QCommonStyle::subControlRect(control, option, subControl, widget); if (!d->isThemeAvailable()) - return QWindowsStyle::subControlRect(control, option, subControl, widget); + return QCommonStyle::subControlRect(control, option, subControl, widget); switch (control) { case CC_ScrollBar: @@ -3777,7 +3779,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple GtkWidget *arrowWidget = d->gtkWidget(arrowPath); if (!arrowWidget) - return QWindowsStyle::subControlRect(control, option, subControl, widget); + return QCommonStyle::subControlRect(control, option, subControl, widget); GtkAllocation allocation; d->gtk_widget_get_allocation(arrowWidget, &allocation); @@ -3826,7 +3828,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, { Q_D(const QGtkStyle); - QSize newSize = QWindowsStyle::sizeFromContents(type, option, size, widget); + QSize newSize = QCommonStyle::sizeFromContents(type, option, size, widget); if (!d->isThemeAvailable()) return newSize; @@ -3862,34 +3864,6 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, newSize += QSize(6, 0); } break; - case CT_MenuItem: - if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { - int textMargin = 8; - - if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { - GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem"); - GtkRequisition sizeReq = {0, 0}; - d->gtk_widget_size_request(gtkMenuSeparator, &sizeReq); - newSize = QSize(size.width(), sizeReq.height); - break; - } - - GtkWidget *gtkMenuItem = d->gtkWidget("GtkMenu.GtkCheckMenuItem"); - GtkStyle* style = d->gtk_widget_get_style(gtkMenuItem); - - // Note we get the perfect height for the default font since we - // set a fake text label on the gtkMenuItem - // But if custom fonts are used on the widget we need a minimum size - GtkRequisition sizeReq = {0, 0}; - d->gtk_widget_size_request(gtkMenuItem, &sizeReq); - newSize.setHeight(qMax(newSize.height() - 4, sizeReq.height)); - newSize += QSize(textMargin + style->xthickness - 1, 0); - - gint checkSize; - d->gtk_widget_style_get(gtkMenuItem, "indicator-size", &checkSize, NULL); - newSize.setWidth(newSize.width() + qMax(0, checkSize - 20)); - } - break; case CT_SpinBox: // QSpinBox does some nasty things that depends on CT_LineEdit newSize = size + QSize(0, -d->gtk_widget_get_style(d->gtkWidget("GtkSpinButton"))->ythickness * 2); @@ -3954,7 +3928,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, newSize += QSize(1, 1); break; case CT_MenuBarItem: - newSize += QSize(0, 2); + newSize += QSize(QGtkStylePrivate::menuItemHMargin * 4, QGtkStylePrivate::menuItemVMargin * 2 + 2); break; case CT_SizeGrip: newSize += QSize(4, 4); @@ -3973,6 +3947,56 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, newSize = QSize(60, 19); } break; + case CT_MenuItem: + if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { + int w = newSize.width(); + int maxpmw = menuItem->maxIconWidth; + int tabSpacing = 20; + if (menuItem->text.contains(QLatin1Char('\t'))) + w += tabSpacing; + else if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) + w += 2 * QGtkStylePrivate::menuArrowHMargin; + else if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) { + // adjust the font and add the difference in size. + // it would be better if the font could be adjusted in the initStyleOption qmenu func!! + QFontMetrics fm(menuItem->font); + QFont fontBold = menuItem->font; + fontBold.setBold(true); + QFontMetrics fmBold(fontBold); + w += fmBold.width(menuItem->text) - fm.width(menuItem->text); + } + + int checkcol = qMax<int>(maxpmw, QGtkStylePrivate::menuCheckMarkWidth); // Windows always shows a check column + w += checkcol; + w += int(QGtkStylePrivate::menuRightBorder) + 10; + + newSize.setWidth(w); + + int textMargin = 8; + if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { + GtkWidget *gtkMenuSeparator = d->gtkWidget("GtkMenu.GtkSeparatorMenuItem"); + GtkRequisition sizeReq = {0, 0}; + d->gtk_widget_size_request(gtkMenuSeparator, &sizeReq); + newSize = QSize(newSize.width(), sizeReq.height); + break; + } + + GtkWidget *gtkMenuItem = d->gtkWidget("GtkMenu.GtkCheckMenuItem"); + GtkStyle* style = d->gtk_widget_get_style(gtkMenuItem); + + // Note we get the perfect height for the default font since we + // set a fake text label on the gtkMenuItem + // But if custom fonts are used on the widget we need a minimum size + GtkRequisition sizeReq = {0, 0}; + d->gtk_widget_size_request(gtkMenuItem, &sizeReq); + newSize.setHeight(qMax(newSize.height() - 4, sizeReq.height)); + newSize += QSize(textMargin + style->xthickness - 1, 0); + + gint checkSize; + d->gtk_widget_style_get(gtkMenuItem, "indicator-size", &checkSize, NULL); + newSize.setWidth(newSize.width() + qMax(0, checkSize - 20)); + } + break; default: break; } @@ -3988,7 +4012,7 @@ QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, Q_D(const QGtkStyle); if (!d->isThemeAvailable()) - return QWindowsStyle::standardPixmap(sp, option, widget); + return QCommonStyle::standardPixmap(sp, option, widget); QPixmap pixmap; switch (sp) { @@ -4042,7 +4066,7 @@ QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, case SP_MessageBoxCritical: return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG); default: - return QWindowsStyle::standardPixmap(sp, option, widget); + return QCommonStyle::standardPixmap(sp, option, widget); } return pixmap; } @@ -4057,7 +4081,7 @@ QIcon QGtkStyle::standardIcon(StandardPixmap standardIcon, Q_D(const QGtkStyle); if (!d->isThemeAvailable()) - return QWindowsStyle::standardIcon(standardIcon, option, widget); + return QCommonStyle::standardIcon(standardIcon, option, widget); switch (standardIcon) { case SP_DialogDiscardButton: return QGtkPainter::getIcon(GTK_STOCK_DELETE); @@ -4086,7 +4110,7 @@ QIcon QGtkStyle::standardIcon(StandardPixmap standardIcon, case SP_MessageBoxCritical: return QGtkPainter::getIcon(GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_DIALOG); default: - return QWindowsStyle::standardIcon(standardIcon, option, widget); + return QCommonStyle::standardIcon(standardIcon, option, widget); } } @@ -4096,7 +4120,7 @@ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, { Q_D(const QGtkStyle); - QRect r = QWindowsStyle::subElementRect(element, option, widget); + QRect r = QCommonStyle::subElementRect(element, option, widget); if (!d->isThemeAvailable()) return r; @@ -4149,7 +4173,7 @@ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option, */ QRect QGtkStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const { - return QWindowsStyle::itemPixmapRect(r, flags, pixmap); + return QCommonStyle::itemPixmapRect(r, flags, pixmap); } /*! @@ -4158,7 +4182,7 @@ QRect QGtkStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap void QGtkStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const { - QWindowsStyle::drawItemPixmap(painter, rect, alignment, pixmap); + QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap); } /*! @@ -4167,7 +4191,7 @@ void QGtkStyle::drawItemPixmap(QPainter *painter, const QRect &rect, QStyle::SubControl QGtkStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, const QPoint &pt, const QWidget *w) const { - return QWindowsStyle::hitTestComplexControl(cc, opt, pt, w); + return QCommonStyle::hitTestComplexControl(cc, opt, pt, w); } /*! @@ -4176,7 +4200,7 @@ QStyle::SubControl QGtkStyle::hitTestComplexControl(ComplexControl cc, const QSt QPixmap QGtkStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const { - return QWindowsStyle::generatedIconPixmap(iconMode, pixmap, opt); + return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt); } /*! @@ -4185,7 +4209,7 @@ QPixmap QGtkStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixm void QGtkStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, const QPalette &pal, bool enabled, const QString& text, QPalette::ColorRole textRole) const { - return QWindowsStyle::drawItemText(painter, rect, alignment, pal, enabled, text, textRole); + return QCommonStyle::drawItemText(painter, rect, alignment, pal, enabled, text, textRole); } QT_END_NAMESPACE diff --git a/src/widgets/styles/qgtkstyle.h b/src/widgets/styles/qgtkstyle.h index 446305b6ba..c0faca075c 100644 --- a/src/widgets/styles/qgtkstyle.h +++ b/src/widgets/styles/qgtkstyle.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE class QPainterPath; class QGtkStylePrivate; -class Q_WIDGETS_EXPORT QGtkStyle : public QWindowsStyle +class Q_WIDGETS_EXPORT QGtkStyle : public QCommonStyle { Q_OBJECT Q_DECLARE_PRIVATE(QGtkStyle) diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp index 85b645c71c..3bd5688f31 100644 --- a/src/widgets/styles/qgtkstyle_p.cpp +++ b/src/widgets/styles/qgtkstyle_p.cpp @@ -289,10 +289,11 @@ QList<QGtkStylePrivate *> QGtkStylePrivate::instances; QGtkStylePrivate::WidgetMap *QGtkStylePrivate::widgetMap = 0; QGtkStylePrivate::QGtkStylePrivate() - : QWindowsStylePrivate() + : QCommonStylePrivate() , filter(this) { instances.append(this); + animationFps = 60; } QGtkStylePrivate::~QGtkStylePrivate() diff --git a/src/widgets/styles/qgtkstyle_p.h b/src/widgets/styles/qgtkstyle_p.h index 009d49ecbe..71c70c41f1 100644 --- a/src/widgets/styles/qgtkstyle_p.h +++ b/src/widgets/styles/qgtkstyle_p.h @@ -63,7 +63,7 @@ #include <QtWidgets/QFileDialog> #include <QtWidgets/QGtkStyle> -#include <private/qwindowsstyle_p.h> +#include <private/qcommonstyle_p.h> #undef signals // Collides with GTK symbols #include <gtk/gtk.h> @@ -317,7 +317,7 @@ typedef char* (*Ptr_gnome_icon_lookup_sync) ( GnomeIconLookupFlags flags, GnomeIconLookupResultFlags *result); -class QGtkStylePrivate : public QWindowsStylePrivate +class QGtkStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QGtkStyle) public: @@ -522,6 +522,15 @@ protected: virtual void init(); + enum { + menuItemFrame = 2, // menu item frame width + menuItemHMargin = 3, // menu item hor text margin + menuArrowHMargin = 6, // menu arrow horizontal margin + menuItemVMargin = 2, // menu item ver text margin + menuRightBorder = 15, // right border on menus + menuCheckMarkWidth = 12 // checkmarks width on menus + }; + private: static QList<QGtkStylePrivate *> instances; static WidgetMap *widgetMap; diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index ecb3e7f222..38f4dc3abc 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -101,7 +101,9 @@ #include <QtWidgets/qgraphicsproxywidget.h> #include <QtWidgets/qgraphicsview.h> #include <private/qstylehelper_p.h> +#include <private/qstyleanimation_p.h> #include <qpa/qplatformfontdatabase.h> +#include <qpa/qplatformtheme.h> QT_USE_NAMESPACE @@ -125,9 +127,9 @@ QMacStylePrivate *mPrivate; { Q_UNUSED(notification); QEvent event(QEvent::StyleChange); - Q_FOREACH (QPointer<QWidget> sb, mPrivate->scrollBars) { - if (sb) - QCoreApplication::sendEvent(sb, &event); + Q_FOREACH (const QObject* target, mPrivate->animationTargets()) { + if (target) + QCoreApplication::sendEvent(const_cast<QObject*>(target), &event); } } @end @@ -1011,7 +1013,7 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg if (!widg || !qobject_cast<QComboBox *>(widg->parentWidget())) { //should I take into account the font dimentions of the lineedit? -Sam if (sz == QAquaSizeLarge) - ret = QSize(-1, 22); + ret = QSize(-1, 21); else ret = QSize(-1, 19); } @@ -1390,7 +1392,7 @@ HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int butt switch (buttonKind){ case kThemePopupButton: innerBounds.origin.x += 2; - innerBounds.origin.y += 3; + innerBounds.origin.y += 2; innerBounds.size.width -= 5; innerBounds.size.height -= 6; break; @@ -1408,9 +1410,9 @@ HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int butt break; case kThemeComboBox: innerBounds.origin.x += 3; - innerBounds.origin.y += 3; + innerBounds.origin.y += 2; innerBounds.size.width -= 6; - innerBounds.size.height -= 6; + innerBounds.size.height -= 8; break; case kThemeComboBoxSmall: innerBounds.origin.x += 3; @@ -1439,7 +1441,7 @@ QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThe QRect ret = outerBounds; switch (bdi.kind){ case kThemeComboBox: - ret.adjust(5, 8, -23, -4); + ret.adjust(5, 5, -22, -5); break; case kThemeComboBoxSmall: ret.adjust(4, 5, -18, 0); @@ -1450,7 +1452,7 @@ QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThe ret.setHeight(13); break; case kThemePopupButton: - ret.adjust(10, 3, -23, -3); + ret.adjust(10, 2, -23, -4); break; case kThemePopupButtonSmall: ret.adjust(9, 3, -20, -3); @@ -1668,7 +1670,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti } QMacStylePrivate::QMacStylePrivate() - : timerID(-1), progressFrame(0), mouseDown(false) + : mouseDown(false) { defaultButtonStart = CFAbsoluteTimeGetCurrent(); memset(&buttonState, 0, sizeof(ButtonState)); @@ -1681,69 +1683,50 @@ QMacStylePrivate::QMacStylePrivate() } -bool QMacStylePrivate::animatable(QMacStylePrivate::Animates as, const QWidget *w) const +bool QMacStylePrivate::animatable(QMacStylePrivate::Animates as, const QObject *obj) const { - if (!w) + if (!obj) return false; if (as == AquaPushButton) { - QPushButton *pb = const_cast<QPushButton *>(static_cast<const QPushButton *>(w)); - if (w->window()->isActiveWindow() && pb && !mouseDown) { - if (static_cast<const QPushButton *>(w) != defaultButton) { + QPushButton *pb = const_cast<QPushButton *>(qobject_cast<const QPushButton *>(obj)); + if (pb && pb->window()->isActiveWindow() && !mouseDown) { + if (pb != defaultButton) { // Changed on its own, update the value. const_cast<QMacStylePrivate *>(this)->stopAnimate(as, defaultButton); const_cast<QMacStylePrivate *>(this)->startAnimate(as, pb); } return true; } - } else if (as == AquaProgressBar) { - if (progressBars.contains((const_cast<QWidget *>(w)))) - return true; - } else if (as == AquaScrollBar) { - if (scrollBars.contains((const_cast<QWidget *>(w)))) - return true; } - return false; + return animation(obj); } -void QMacStylePrivate::stopAnimate(QMacStylePrivate::Animates as, QWidget *w) +void QMacStylePrivate::stopAnimate(QMacStylePrivate::Animates as, QObject *obj) { + stopAnimation(obj); if (as == AquaPushButton && defaultButton) { + stopAnimation(defaultButton); QPushButton *tmp = defaultButton; defaultButton = 0; tmp->update(); - } else if (as == AquaProgressBar) { - progressBars.removeAll(w); } else if (as == AquaScrollBar) { - scrollBars.removeAll(w); - scrollBarInfos.remove(w); + scrollBarInfos.remove(qobject_cast<QWidget*>(obj)); } } -void QMacStylePrivate::startAnimate(QMacStylePrivate::Animates as, QWidget *w) +void QMacStylePrivate::startAnimate(QMacStylePrivate::Animates as, QObject *obj) { + if (!animation(obj)) + startAnimation(new QStyleAnimation(obj)); if (as == AquaPushButton) - defaultButton = static_cast<QPushButton *>(w); - else if (as == AquaProgressBar) - progressBars.append(w); - else if (as == AquaScrollBar) - scrollBars.append(w); - startAnimationTimer(); -} - -void QMacStylePrivate::startAnimationTimer() -{ - Q_Q(QMacStyle); - if ((defaultButton || !progressBars.isEmpty() || !scrollBars.isEmpty()) && timerID <= -1) - timerID = q->startTimer(animateSpeed(AquaListViewItemOpen)); + defaultButton = qobject_cast<QPushButton *>(obj); } bool QMacStylePrivate::addWidget(QWidget *w) { //already knew of it - if (static_cast<QPushButton*>(w) == defaultButton - || progressBars.contains(static_cast<QProgressBar*>(w)) - || scrollBars.contains(static_cast<QScrollBar*>(w))) + if (w == defaultButton || animation(w)) return false; Q_Q(QMacStyle); @@ -1753,12 +1736,6 @@ bool QMacStylePrivate::addWidget(QWidget *w) startAnimate(AquaPushButton, btn); return true; } else { - bool isProgressBar = (qobject_cast<QProgressBar *>(w)); - if (isProgressBar) { - w->installEventFilter(q); - startAnimate(AquaProgressBar, w); - return true; - } bool isScrollBar = (qobject_cast<QScrollBar *>(w)); if (isScrollBar) { w->installEventFilter(q); @@ -1778,8 +1755,6 @@ void QMacStylePrivate::removeWidget(QWidget *w) QPushButton *btn = qobject_cast<QPushButton *>(w); if (btn && btn == defaultButton) { stopAnimate(AquaPushButton, btn); - } else if (qobject_cast<QProgressBar *>(w)) { - stopAnimate(AquaProgressBar, w); } else if (qobject_cast<QScrollBar *>(w)) { stopAnimate(AquaScrollBar, w); } @@ -1802,87 +1777,13 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) return tds; } -void QMacStylePrivate::animate() -{ - Q_Q(QMacStyle); - int animated = 0; - if (defaultButton && defaultButton->isEnabled() && defaultButton->window()->isActiveWindow() - && defaultButton->isVisibleTo(0) && (defaultButton->isDefault() - || (defaultButton->autoDefault() && defaultButton->hasFocus())) - && doAnimate(AquaPushButton)) { - ++animated; - defaultButton->update(); - } - if (!progressBars.isEmpty()) { - int i = 0; - while (i < progressBars.size()) { - QWidget *maybeProgress = progressBars.at(i); - if (!maybeProgress) { - progressBars.removeAt(i); - } else { - if (QProgressBar *pb = qobject_cast<QProgressBar *>(maybeProgress)) { - if (pb->maximum() == 0 || (pb->value() > 0 && pb->value() < pb->maximum())) { - if (doAnimate(AquaProgressBar)) - pb->update(); - } - } - ++i; - } - } - if (i > 0) { - ++progressFrame; - animated += i; - } - } - if (!scrollBars.isEmpty()) { - int i = 0; - const qint64 dt = QDateTime::currentMSecsSinceEpoch(); - while (i < scrollBars.size()) { - QWidget *maybeScroll = scrollBars.at(i); - if (!maybeScroll) { - scrollBars.removeAt(i); - } else { - if (QScrollBar *sb = qobject_cast<QScrollBar *>(maybeScroll)) { - const OverlayScrollBarInfo& info = scrollBarInfos[sb]; - const qreal elapsed = qMax(dt - info.lastHovered, - dt - info.lastUpdate); - const CGFloat opacity = 1.0 - qMax(0.0, (elapsed - ScrollBarFadeOutDelay) / - ScrollBarFadeOutDuration); - if ((opacity > 0.0 || !info.cleared) && (elapsed > ScrollBarFadeOutDelay)) { - if (doAnimate(AquaScrollBar)) - sb->update(); - } - } - ++i; - ++animated; - } - } - } - if (animated <= 0) { - q->killTimer(timerID); - timerID = -1; - } -} - /*! \reimp */ bool QMacStyle::eventFilter(QObject *o, QEvent *e) { //animate Q_D(QMacStyle); - if (QProgressBar *pb = qobject_cast<QProgressBar *>(o)) { - switch (e->type()) { - default: - break; - case QEvent::Show: - if (!d->progressBars.contains(pb)) - d->startAnimate(QMacStylePrivate::AquaProgressBar, pb); - break; - case QEvent::Destroy: - case QEvent::Hide: - d->progressBars.removeAll(pb); - } + if (QScrollBar *sb = qobject_cast<QScrollBar *>(o)) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - } else if (QScrollBar *sb = qobject_cast<QScrollBar *>(o)) { // take care of fading out overlaying scrollbars (and only those!) when inactive const QAbstractScrollArea *scrollArea = scrollBarsScrollArea(sb); if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7 && @@ -1986,17 +1887,6 @@ bool QMacStyle::eventFilter(QObject *o, QEvent *e) return false; } -bool QMacStylePrivate::doAnimate(QMacStylePrivate::Animates as) -{ - if (as == AquaPushButton) { - } else if (as == AquaProgressBar) { - // something for later... - } else if (as == AquaListViewItemOpen) { - // To be revived later... - } - return true; -} - void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi, QPainter *p, const QStyleOption *opt) const { @@ -2390,9 +2280,6 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW // The combo box popup has no frame. if (qstyleoption_cast<const QStyleOptionComboBox *>(opt) != 0) ret = 0; - // Frame of mac style line edits is two pixels on top and one on the bottom - else if (qobject_cast<const QLineEdit *>(widget) != 0) - ret = 2; else ret = 1; break; @@ -3754,7 +3641,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter bdi.adornment |= kThemeAdornmentDefault; bdi.animation.time.start = d->defaultButtonStart; bdi.animation.time.current = CFAbsoluteTimeGetCurrent(); - const_cast<QMacStylePrivate*>(d)->startAnimationTimer(); } // Unlike Carbon, we want the button to always be drawn inside its bounds. // Therefore, make the button a bit smaller, so that even if it got focus, @@ -4462,7 +4348,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tdi.min = pb->minimum; tdi.value = pb->progress; tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; - tdi.trackInfo.progress.phase = d->progressFrame; + if (isIndeterminate) { + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject))) + tdi.trackInfo.progress.phase = animation->animationStep(); + else + d->startAnimation(new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject)); + } else { + d->stopAnimation(opt->styleObject); + } if (!(pb->state & State_Active)) tdi.enableState = kThemeTrackInactive; else if (!(pb->state & State_Enabled)) @@ -4762,7 +4655,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, if(widget->parentWidget() && qobject_cast<const QComboBox*>(widget->parentWidget())) rect.adjust(-1, -2, 0, 0); else - rect.adjust(-1, 0, 0, +1); + rect.adjust(-1, -1, 0, +1); break; case SE_CheckBoxLayoutItem: rect = opt->rect; @@ -6514,9 +6407,6 @@ bool QMacStyle::event(QEvent *e) } else if(e->type() == QEvent::FocusOut) { if(d->focusWidget) d->focusWidget->setWidget(0); - } else if (e->type() == QEvent::Timer) { - if (static_cast<QTimerEvent*>(e)->timerId() == d->timerID) - d->animate(); } return false; } diff --git a/src/widgets/styles/qmacstyle_mac_p.h b/src/widgets/styles/qmacstyle_mac_p.h index ac482b8fc7..812c79e158 100644 --- a/src/widgets/styles/qmacstyle_mac_p.h +++ b/src/widgets/styles/qmacstyle_mac_p.h @@ -163,17 +163,15 @@ public: void removeWidget(QWidget *); enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar }; - bool animatable(Animates, const QWidget *) const; - void stopAnimate(Animates, QWidget *); - void startAnimate(Animates, QWidget *); + bool animatable(Animates, const QObject *) const; + void stopAnimate(Animates, QObject *); + void startAnimate(Animates, QObject *); static ThemeDrawState getDrawState(QStyle::State flags); QAquaWidgetSize aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, QStyle::ContentsType ct = QStyle::CT_CustomBase, QSize szHint=QSize(-1, -1), QSize *insz = 0) const; void getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const; - void animate(); - bool doAnimate(Animates); inline int animateSpeed(Animates) const { return 33; } // Utility functions @@ -202,13 +200,8 @@ public: HIThemeButtonDrawInfo *bdi) const; QPixmap generateBackgroundPattern() const; - void startAnimationTimer(); - public: QPointer<QPushButton> defaultButton; //default push buttons - int timerID; - QList<QPointer<QWidget> > progressBars; //existing progress bars that need animation - QList<QPointer<QWidget> > scrollBars; //existing scroll bars that need animation struct OverlayScrollBarInfo { OverlayScrollBarInfo() @@ -235,7 +228,6 @@ public: int frame; enum { ButtonDark, ButtonLight } dir; } buttonState; - UInt8 progressFrame; mutable QPointer<QFocusFrame> focusWidget; CFAbsoluteTime defaultButtonStart; bool mouseDown; diff --git a/src/widgets/styles/qplastiquestyle.cpp b/src/widgets/styles/qplastiquestyle.cpp index d22f82ff85..449783fb90 100644 --- a/src/widgets/styles/qplastiquestyle.cpp +++ b/src/widgets/styles/qplastiquestyle.cpp @@ -79,7 +79,6 @@ static const int blueFrameWidth = 2; // with of line edit focus frame #include <qsplitter.h> #include <qstyleoption.h> #include <qtextedit.h> -#include <qelapsedtimer.h> #include <qtoolbar.h> #include <qtoolbox.h> #include <qtoolbutton.h> @@ -89,6 +88,7 @@ static const int blueFrameWidth = 2; // with of line edit focus frame #include <private/qstylehelper_p.h> #include <qpa/qplatformtheme.h> #include <private/qguiapplication_p.h> +#include <private/qstyleanimation_p.h> QT_BEGIN_NAMESPACE @@ -987,12 +987,6 @@ public: virtual ~QPlastiqueStylePrivate(); void drawPartialFrame(QPainter *painter, const QStyleOptionComplex *option, const QRect &rect, const QWidget *widget) const; - -#ifndef QT_NO_PROGRESSBAR - QList<QProgressBar *> bars; - int progressBarAnimateTimer; - QElapsedTimer timer; -#endif }; /*! @@ -1000,9 +994,6 @@ public: */ QPlastiqueStylePrivate::QPlastiqueStylePrivate() : QWindowsStylePrivate() -#ifndef QT_NO_PROGRESSBAR - , progressBarAnimateTimer(0) -#endif { } @@ -2405,7 +2396,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op } break; #endif // QT_NO_TABBAR -#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarGroove: if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { QRect rect = bar->rect; @@ -2575,11 +2566,14 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op } else { progressBar.setRect(rect.right() - 1 - width, rect.top() + 2, width, rect.height() - 4); } + d->stopAnimation(option->styleObject); } else { int slideWidth = ((rect.width() - 4) * 2) / 3; - int step = ((d->animateStep * slideWidth) / ProgressBarFps) % slideWidth; - if ((((d->animateStep * slideWidth) / ProgressBarFps) % (2 * slideWidth)) >= slideWidth) - step = slideWidth - step; + int step = 0; + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(option->styleObject))) + step = animation->progressStep(slideWidth); + else + d->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject)); progressBar.setRect(rect.left() + 2 + step, rect.top() + 2, slideWidth / 2, rect.height() - 4); } @@ -2732,7 +2726,11 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op if (!vertical) progressBar.adjust(0, 1, 0, 1); if (!indeterminate) { - int step = (AnimateProgressBar || (indeterminate && AnimateBusyProgressBar)) ? (d->animateStep % 20) : 0; + int step = 0; + if (AnimateProgressBar || (indeterminate && AnimateBusyProgressBar)) { + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(widget))) + step = animation->animationStep() % 20; + } if (reverse) painter->drawPixmap(progressBar.left() - 25 + step, progressBar.top(), cache); else @@ -2744,7 +2742,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op painter->restore(); } break; -#endif // QT_NO_PROGRESSBAR + case CE_HeaderSection: // Draws the header in tables. if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { @@ -4957,12 +4955,10 @@ QRect QPlastiqueStyle::subElementRect(SubElement element, const QStyleOption *op rect = visualRect(option->direction, option->rect, QWindowsStyle::subElementRect(element, option, widget)).adjusted(0, 0, 1, 1); break; -#ifndef QT_NO_PROGRESSBAR case SE_ProgressBarLabel: case SE_ProgressBarContents: case SE_ProgressBarGroove: return option->rect; -#endif // QT_NO_PROGRESSBAR default: return QWindowsStyle::subElementRect(element, option, widget); } @@ -5648,11 +5644,6 @@ void QPlastiqueStyle::polish(QWidget *widget) widget->setBackgroundRole(QPalette::Window); } -#ifndef QT_NO_PROGRESSBAR - if (AnimateBusyProgressBar && qobject_cast<QProgressBar *>(widget)) - widget->installEventFilter(this); -#endif - #if defined QPlastique_MaskButtons if (qobject_cast<QPushButton *>(widget) || qobject_cast<QToolButton *>(widget)) widget->installEventFilter(this); @@ -5705,14 +5696,6 @@ void QPlastiqueStyle::unpolish(QWidget *widget) widget->setBackgroundRole(QPalette::Button); } -#ifndef QT_NO_PROGRESSBAR - if (AnimateBusyProgressBar && qobject_cast<QProgressBar *>(widget)) { - Q_D(QPlastiqueStyle); - widget->removeEventFilter(this); - d->bars.removeAll(static_cast<QProgressBar*>(widget)); - } -#endif - #if defined QPlastique_MaskButtons if (qobject_cast<QPushButton *>(widget) || qobject_cast<QToolButton *>(widget)) widget->removeEventFilter(this); @@ -5829,31 +5812,8 @@ int QPlastiqueStyle::layoutSpacing(QSizePolicy::ControlType control1, */ bool QPlastiqueStyle::eventFilter(QObject *watched, QEvent *event) { -#ifndef QT_NO_PROGRESSBAR - Q_D(QPlastiqueStyle); - - switch (event->type()) { - case QEvent::Show: - if (QProgressBar *bar = qobject_cast<QProgressBar *>(watched)) { - d->bars.append(bar); - if (d->bars.size() == 1) { - Q_ASSERT(ProgressBarFps > 0); - d->timer.start(); - d->progressBarAnimateTimer = startTimer(1000 / ProgressBarFps); - } - } - break; - case QEvent::Destroy: - case QEvent::Hide: - if(!d->bars.isEmpty()) { - d->bars.removeAll(reinterpret_cast<QProgressBar*>(watched)); - if (d->bars.isEmpty()) { - killTimer(d->progressBarAnimateTimer); - d->progressBarAnimateTimer = 0; - } - } - break; #if defined QPlastique_MaskButtons + switch (event->type()) { case QEvent::Resize: if (qobject_cast<QPushButton *>(watched) || qobject_cast<QToolButton *>(watched)) { QWidget *widget = qobject_cast<QWidget *>(watched); @@ -5870,35 +5830,14 @@ bool QPlastiqueStyle::eventFilter(QObject *watched, QEvent *event) widget->setMask(region); } break; -#endif default: break; } -#endif // QT_NO_PROGRESSBAR +#endif return QWindowsStyle::eventFilter(watched, event); } -/*! - \reimp -*/ -void QPlastiqueStyle::timerEvent(QTimerEvent *event) -{ -#ifndef QT_NO_PROGRESSBAR - Q_D(QPlastiqueStyle); - - if (event->timerId() == d->progressBarAnimateTimer) { - Q_ASSERT(ProgressBarFps > 0); - d->animateStep = d->timer.elapsed() / (1000 / ProgressBarFps); - foreach (QProgressBar *bar, d->bars) { - if (AnimateProgressBar || (bar->minimum() == 0 && bar->maximum() == 0)) - bar->update(); - } - } -#endif // QT_NO_PROGRESSBAR - event->ignore(); -} - QT_END_NAMESPACE #endif // !defined(QT_NO_STYLE_PLASTIQUE) || defined(QT_PLUGIN) diff --git a/src/widgets/styles/qplastiquestyle.h b/src/widgets/styles/qplastiquestyle.h index 05679a85c3..bda686e215 100644 --- a/src/widgets/styles/qplastiquestyle.h +++ b/src/widgets/styles/qplastiquestyle.h @@ -101,7 +101,6 @@ public: protected: bool eventFilter(QObject *watched, QEvent *event); - void timerEvent(QTimerEvent *event); private: Q_DISABLE_COPY(QPlastiqueStyle) diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 77c647e136..f0d1d2319c 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -1934,6 +1934,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, \value SP_DirClosedIcon The closed directory icon. \value SP_DirIcon The directory icon. \value SP_DirLinkIcon The link to directory icon. + \value SP_DirLinkOpenIcon The link to open directory icon. \value SP_FileIcon The file icon. \value SP_FileLinkIcon The link to file icon. \value SP_FileDialogStart The "start" icon in a file dialog. diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index 539424639b..48491b3e3e 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -731,6 +731,7 @@ public: SP_DirOpenIcon, SP_DirClosedIcon, SP_DirLinkIcon, + SP_DirLinkOpenIcon, SP_FileIcon, SP_FileLinkIcon, SP_ToolBarHorizontalExtensionButton, diff --git a/src/widgets/styles/qstyle.qrc b/src/widgets/styles/qstyle.qrc index 6e04540f51..d835728928 100644 --- a/src/widgets/styles/qstyle.qrc +++ b/src/widgets/styles/qstyle.qrc @@ -1,135 +1,137 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource prefix="/qt-project.org/styles/commonstyle"> -<file>images/filelink-16.png</file> -<file>images/filelink-32.png</file> -<file>images/filelink-128.png</file> -<file>images/file-16.png</file> -<file>images/file-32.png</file> -<file>images/file-128.png</file> -<file>images/newdirectory-16.png</file> -<file>images/newdirectory-32.png</file> -<file>images/newdirectory-128.png</file> -<file>images/parentdir-16.png</file> -<file>images/parentdir-32.png</file> -<file>images/parentdir-128.png</file> -<file>images/dvd-16.png</file> -<file>images/dvd-32.png</file> -<file>images/dvd-128.png</file> -<file>images/cdr-16.png</file> -<file>images/cdr-32.png</file> -<file>images/cdr-128.png</file> -<file>images/floppy-16.png</file> -<file>images/floppy-32.png</file> -<file>images/floppy-128.png</file> -<file>images/harddrive-16.png</file> -<file>images/harddrive-32.png</file> -<file>images/harddrive-128.png</file> -<file>images/trash-16.png</file> -<file>images/trash-32.png</file> -<file>images/trash-128.png</file> -<file>images/networkdrive-16.png</file> -<file>images/networkdrive-32.png</file> -<file>images/networkdrive-128.png</file> -<file>images/computer-16.png</file> -<file>images/computer-32.png</file> -<file>images/desktop-16.png</file> -<file>images/desktop-32.png</file> -<file>images/dirclosed-16.png</file> -<file>images/dirclosed-32.png</file> -<file>images/dirclosed-128.png</file> -<file>images/dirlink-16.png</file> -<file>images/dirlink-32.png</file> -<file>images/dirlink-128.png</file> -<file>images/diropen-16.png</file> -<file>images/diropen-32.png</file> -<file>images/diropen-128.png</file> -<file>images/left-16.png</file> -<file>images/left-32.png</file> -<file>images/left-128.png</file> -<file>images/right-16.png</file> -<file>images/right-32.png</file> -<file>images/right-128.png</file> -<file>images/up-16.png</file> -<file>images/up-32.png</file> -<file>images/up-128.png</file> -<file>images/down-16.png</file> -<file>images/down-32.png</file> -<file>images/down-128.png</file> -<file>images/filecontents-16.png</file> -<file>images/filecontents-32.png</file> -<file>images/filecontents-128.png</file> -<file>images/fileinfo-16.png</file> -<file>images/fileinfo-32.png</file> -<file>images/fileinfo-128.png</file> -<file>images/viewdetailed-16.png</file> -<file>images/viewdetailed-32.png</file> -<file>images/viewdetailed-128.png</file> -<file>images/viewlist-16.png</file> -<file>images/viewlist-32.png</file> -<file>images/viewlist-128.png</file> -<file>images/fontbitmap-16.png</file> -<file>images/fonttruetype-16.png</file> -<file>images/standardbutton-apply-128.png</file> -<file>images/standardbutton-apply-16.png</file> -<file>images/standardbutton-apply-32.png</file> -<file>images/standardbutton-cancel-128.png</file> -<file>images/standardbutton-cancel-16.png</file> -<file>images/standardbutton-cancel-32.png</file> -<file>images/standardbutton-clear-128.png</file> -<file>images/standardbutton-clear-16.png</file> -<file>images/standardbutton-clear-32.png</file> -<file>images/standardbutton-close-128.png</file> -<file>images/standardbutton-close-16.png</file> -<file>images/standardbutton-close-32.png</file> -<file>images/standardbutton-delete-128.png</file> -<file>images/standardbutton-delete-16.png</file> -<file>images/standardbutton-delete-32.png</file> -<file>images/standardbutton-help-128.png</file> -<file>images/standardbutton-help-16.png</file> -<file>images/standardbutton-help-32.png</file> -<file>images/standardbutton-no-128.png</file> -<file>images/standardbutton-no-16.png</file> -<file>images/standardbutton-no-32.png</file> -<file>images/standardbutton-ok-128.png</file> -<file>images/standardbutton-ok-16.png</file> -<file>images/standardbutton-ok-32.png</file> -<file>images/standardbutton-open-128.png</file> -<file>images/standardbutton-open-16.png</file> -<file>images/standardbutton-open-32.png</file> -<file>images/standardbutton-save-128.png</file> -<file>images/standardbutton-save-16.png</file> -<file>images/standardbutton-save-32.png</file> -<file>images/standardbutton-yes-128.png</file> -<file>images/standardbutton-yes-16.png</file> -<file>images/standardbutton-yes-32.png</file> -<file>images/standardbutton-closetab-16.png</file> -<file>images/standardbutton-closetab-down-16.png</file> -<file>images/standardbutton-closetab-hover-16.png</file> -<file>images/refresh-24.png</file> -<file>images/refresh-32.png</file> -<file>images/stop-24.png</file> -<file>images/stop-32.png</file> -<file>images/media-stop-16.png</file> -<file>images/media-stop-32.png</file> -<file>images/media-play-16.png</file> -<file>images/media-play-32.png</file> -<file>images/media-pause-16.png</file> -<file>images/media-pause-32.png</file> -<file>images/media-seek-forward-16.png</file> -<file>images/media-seek-forward-32.png</file> -<file>images/media-seek-backward-16.png</file> -<file>images/media-seek-backward-32.png</file> -<file>images/media-skip-forward-16.png</file> -<file>images/media-skip-forward-32.png</file> -<file>images/media-skip-backward-16.png</file> -<file>images/media-skip-backward-32.png</file> -<file>images/media-volume-16.png</file> -<file>images/media-volume-muted-16.png</file> -</qresource> -<qresource prefix="/qt-project.org/styles/macstyle"> -<file>images/closedock-16.png</file> -<file>images/closedock-down-16.png</file> -<file>images/dockdock-16.png</file> -<file>images/dockdock-down-16.png</file> -</qresource> +<RCC> + <qresource prefix="/qt-project.org/styles/commonstyle"> + <file>images/filelink-16.png</file> + <file>images/filelink-32.png</file> + <file>images/filelink-128.png</file> + <file>images/file-16.png</file> + <file>images/file-32.png</file> + <file>images/file-128.png</file> + <file>images/newdirectory-16.png</file> + <file>images/newdirectory-32.png</file> + <file>images/newdirectory-128.png</file> + <file>images/parentdir-16.png</file> + <file>images/parentdir-32.png</file> + <file>images/parentdir-128.png</file> + <file>images/dvd-16.png</file> + <file>images/dvd-32.png</file> + <file>images/dvd-128.png</file> + <file>images/cdr-16.png</file> + <file>images/cdr-32.png</file> + <file>images/cdr-128.png</file> + <file>images/floppy-16.png</file> + <file>images/floppy-32.png</file> + <file>images/floppy-128.png</file> + <file>images/harddrive-16.png</file> + <file>images/harddrive-32.png</file> + <file>images/harddrive-128.png</file> + <file>images/trash-16.png</file> + <file>images/trash-32.png</file> + <file>images/trash-128.png</file> + <file>images/networkdrive-16.png</file> + <file>images/networkdrive-32.png</file> + <file>images/networkdrive-128.png</file> + <file>images/computer-16.png</file> + <file>images/computer-32.png</file> + <file>images/desktop-16.png</file> + <file>images/desktop-32.png</file> + <file>images/dirclosed-16.png</file> + <file>images/dirclosed-32.png</file> + <file>images/dirclosed-128.png</file> + <file>images/dirlink-16.png</file> + <file>images/dirlink-32.png</file> + <file>images/dirlink-128.png</file> + <file>images/diropen-16.png</file> + <file>images/diropen-32.png</file> + <file>images/diropen-128.png</file> + <file>images/left-16.png</file> + <file>images/left-32.png</file> + <file>images/left-128.png</file> + <file>images/right-16.png</file> + <file>images/right-32.png</file> + <file>images/right-128.png</file> + <file>images/up-16.png</file> + <file>images/up-32.png</file> + <file>images/up-128.png</file> + <file>images/down-16.png</file> + <file>images/down-32.png</file> + <file>images/down-128.png</file> + <file>images/filecontents-16.png</file> + <file>images/filecontents-32.png</file> + <file>images/filecontents-128.png</file> + <file>images/fileinfo-16.png</file> + <file>images/fileinfo-32.png</file> + <file>images/fileinfo-128.png</file> + <file>images/viewdetailed-16.png</file> + <file>images/viewdetailed-32.png</file> + <file>images/viewdetailed-128.png</file> + <file>images/viewlist-16.png</file> + <file>images/viewlist-32.png</file> + <file>images/viewlist-128.png</file> + <file>images/fontbitmap-16.png</file> + <file>images/fonttruetype-16.png</file> + <file>images/standardbutton-apply-128.png</file> + <file>images/standardbutton-apply-16.png</file> + <file>images/standardbutton-apply-32.png</file> + <file>images/standardbutton-cancel-128.png</file> + <file>images/standardbutton-cancel-16.png</file> + <file>images/standardbutton-cancel-32.png</file> + <file>images/standardbutton-clear-128.png</file> + <file>images/standardbutton-clear-16.png</file> + <file>images/standardbutton-clear-32.png</file> + <file>images/standardbutton-close-128.png</file> + <file>images/standardbutton-close-16.png</file> + <file>images/standardbutton-close-32.png</file> + <file>images/standardbutton-delete-128.png</file> + <file>images/standardbutton-delete-16.png</file> + <file>images/standardbutton-delete-32.png</file> + <file>images/standardbutton-help-128.png</file> + <file>images/standardbutton-help-16.png</file> + <file>images/standardbutton-help-32.png</file> + <file>images/standardbutton-no-128.png</file> + <file>images/standardbutton-no-16.png</file> + <file>images/standardbutton-no-32.png</file> + <file>images/standardbutton-ok-128.png</file> + <file>images/standardbutton-ok-16.png</file> + <file>images/standardbutton-ok-32.png</file> + <file>images/standardbutton-open-128.png</file> + <file>images/standardbutton-open-16.png</file> + <file>images/standardbutton-open-32.png</file> + <file>images/standardbutton-save-128.png</file> + <file>images/standardbutton-save-16.png</file> + <file>images/standardbutton-save-32.png</file> + <file>images/standardbutton-yes-128.png</file> + <file>images/standardbutton-yes-16.png</file> + <file>images/standardbutton-yes-32.png</file> + <file>images/standardbutton-closetab-16.png</file> + <file>images/standardbutton-closetab-down-16.png</file> + <file>images/standardbutton-closetab-hover-16.png</file> + <file>images/refresh-24.png</file> + <file>images/refresh-32.png</file> + <file>images/stop-24.png</file> + <file>images/stop-32.png</file> + <file>images/media-stop-16.png</file> + <file>images/media-stop-32.png</file> + <file>images/media-play-16.png</file> + <file>images/media-play-32.png</file> + <file>images/media-pause-16.png</file> + <file>images/media-pause-32.png</file> + <file>images/media-seek-forward-16.png</file> + <file>images/media-seek-forward-32.png</file> + <file>images/media-seek-backward-16.png</file> + <file>images/media-seek-backward-32.png</file> + <file>images/media-skip-forward-16.png</file> + <file>images/media-skip-forward-32.png</file> + <file>images/media-skip-backward-16.png</file> + <file>images/media-skip-backward-32.png</file> + <file>images/media-volume-16.png</file> + <file>images/media-volume-muted-16.png</file> + <file>images/fusion_groupbox.png</file> + <file>images/fusion_arrow.png</file> + </qresource> + <qresource prefix="/qt-project.org/styles/macstyle"> + <file>images/closedock-16.png</file> + <file>images/closedock-down-16.png</file> + <file>images/dockdock-16.png</file> + <file>images/dockdock-down-16.png</file> + </qresource> </RCC> diff --git a/src/widgets/styles/qstyle_p.h b/src/widgets/styles/qstyle_p.h index 66cd7eed10..85e8e54b16 100644 --- a/src/widgets/styles/qstyle_p.h +++ b/src/widgets/styles/qstyle_p.h @@ -72,6 +72,15 @@ public: QStyle *proxyStyle; }; +inline QImage styleCacheImage(const QSize &size) +{ + return QImage(size, QImage::Format_ARGB32_Premultiplied); +} + +inline QPixmap styleCachePixmap(const QSize &size) +{ + return QPixmap(size); +} #define BEGIN_STYLE_PIXMAPCACHE(a) \ QRect rect = option->rect; \ @@ -80,13 +89,14 @@ public: QPainter *p = painter; \ QString unique = QStyleHelper::uniqueName((a), option, option->rect.size()); \ int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \ - bool doPixmapCache = txType <= QTransform::TxTranslate; \ + bool doPixmapCache = (txType <= QTransform::TxTranslate) \ + || (painter->deviceTransform().type() == QTransform::TxScale); \ if (doPixmapCache && QPixmapCache::find(unique, internalPixmapCache)) { \ painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \ } else { \ if (doPixmapCache) { \ rect.setRect(0, 0, option->rect.width(), option->rect.height()); \ - imageCache = QImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); \ + imageCache = styleCacheImage(option->rect.size()); \ imageCache.fill(0); \ p = new QPainter(&imageCache); \ } diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp new file mode 100644 index 0000000000..6173dc9ddb --- /dev/null +++ b/src/widgets/styles/qstyleanimation.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstyleanimation_p.h" +#include <qcoreapplication.h> +#include <qprogressbar.h> +#include <qwidget.h> +#include <qevent.h> + +QT_BEGIN_NAMESPACE + +QStyleAnimation::QStyleAnimation(QObject *target) : QAbstractAnimation(target), + _startTime(QTime::currentTime()) +{ +} + +QStyleAnimation::~QStyleAnimation() +{ +} + +int QStyleAnimation::duration() const +{ + return -1; +} + +QObject *QStyleAnimation::target() const +{ + return parent(); +} + +QTime QStyleAnimation::startTime() const +{ + return _startTime; +} + +void QStyleAnimation::setStartTime(const QTime &time) +{ + _startTime = time; +} + +bool QStyleAnimation::isUpdateNeeded() const +{ + return true; +} + +void QStyleAnimation::updateCurrentTime(int) +{ + if (QObject *tgt = target()) { + if (tgt->isWidgetType()) { + QWidget *widget = static_cast<QWidget *>(tgt); + if (!widget->isVisible() || widget->window()->isMinimized()) + stop(); + } + + if (isUpdateNeeded()) { + QEvent event(QEvent::StyleAnimationUpdate); + QCoreApplication::sendEvent(tgt, &event); + } + } +} + +QProgressStyleAnimation::QProgressStyleAnimation(int speed, QObject *target) : + QStyleAnimation(target), _speed(speed), _step(-1) +{ +} + +int QProgressStyleAnimation::animationStep() const +{ + return currentTime() / (1000.0 / _speed); +} + +int QProgressStyleAnimation::progressStep(int width) const +{ + int step = animationStep(); + int progress = (step * width / _speed) % width; + if (((step * width / _speed) % (2 * width)) >= width) + progress = width - progress; + return progress; +} + +int QProgressStyleAnimation::speed() const +{ + return _speed; +} + +void QProgressStyleAnimation::setSpeed(int speed) +{ + _speed = speed; +} + +bool QProgressStyleAnimation::isUpdateNeeded() const +{ + int current = animationStep(); + if (_step == -1 || _step != current) + { + _step = current; + return true; + } + return false; +} + +QT_END_NAMESPACE diff --git a/src/widgets/styles/qstyleanimation_p.h b/src/widgets/styles/qstyleanimation_p.h new file mode 100644 index 0000000000..8231abbb40 --- /dev/null +++ b/src/widgets/styles/qstyleanimation_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTYLEANIMATION_P_H +#define QSTYLEANIMATION_P_H + +#include "qabstractanimation.h" +#include "qdatetime.h" + +QT_BEGIN_NAMESPACE + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience of +// qcommonstyle.cpp. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +class QStyleAnimation : public QAbstractAnimation +{ + Q_OBJECT + +public: + QStyleAnimation(QObject *target); + virtual ~QStyleAnimation(); + + int duration() const; + QObject *target() const; + + QTime startTime() const; + void setStartTime(const QTime &time); + +protected: + virtual bool isUpdateNeeded() const; + virtual void updateCurrentTime(int time); + +private: + QTime _startTime; +}; + +class QProgressStyleAnimation : public QStyleAnimation +{ + Q_OBJECT + +public: + QProgressStyleAnimation(int speed, QObject *target); + + int animationStep() const; + int progressStep(int width) const; + + int speed() const; + void setSpeed(int speed); + +protected: + bool isUpdateNeeded() const; + +private: + int _speed; + mutable int _step; +}; + +QT_END_NAMESPACE + +#endif // QSTYLEANIMATION_P_H diff --git a/src/widgets/styles/qstylefactory.cpp b/src/widgets/styles/qstylefactory.cpp index f12ea27e78..8f4f014ac8 100644 --- a/src/widgets/styles/qstylefactory.cpp +++ b/src/widgets/styles/qstylefactory.cpp @@ -52,6 +52,9 @@ #ifndef QT_NO_STYLE_CLEANLOOKS #include "qcleanlooksstyle.h" #endif +#ifndef QT_NO_STYLE_FUSION +#include "qfusionstyle.h" +#endif #ifndef QT_NO_STYLE_GTK #include "qgtkstyle.h" #endif @@ -146,6 +149,11 @@ QStyle *QStyleFactory::create(const QString& key) ret = new QPlastiqueStyle; else #endif +#ifndef QT_NO_STYLE_FUSION + if (style == QLatin1String("fusion")) + ret = new QFusionStyle; + else +#endif #ifndef QT_NO_STYLE_CLEANLOOKS if (style == QLatin1String("cleanlooks")) ret = new QCleanlooksStyle; @@ -222,6 +230,10 @@ QStringList QStyleFactory::keys() if (!list.contains(QLatin1String("GTK+"))) list << QLatin1String("GTK+"); #endif +#ifndef QT_NO_STYLE_FUSION + if (!list.contains(QLatin1String("Fusion"))) + list << QLatin1String("Fusion"); +#endif #ifndef QT_NO_STYLE_CLEANLOOKS if (!list.contains(QLatin1String("Cleanlooks"))) list << QLatin1String("Cleanlooks"); diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index b8fbf37333..e23db2b637 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -77,8 +77,13 @@ QString uniqueName(const QString &key, const QStyleOption *option, const QSize & qreal dpiScaled(qreal value) { +#ifdef Q_OS_MAC + // On mac the DPI is allways 72 so we should not scale it + return value; +#else static const qreal scale = qreal(qt_defaultDpiX()) / 96.0; return value * scale; +#endif } diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp index bc363d3a31..53c1cf4559 100644 --- a/src/widgets/styles/qstyleoption.cpp +++ b/src/widgets/styles/qstyleoption.cpp @@ -41,8 +41,7 @@ #include "qstyleoption.h" #include "qapplication.h" -#ifdef Q_WS_MAC -# include "private/qt_mac_p.h" +#ifdef Q_OS_MAC # include "qmacstyle_mac.h" #endif #include <qdebug.h> @@ -155,7 +154,7 @@ QT_BEGIN_NAMESPACE QStyleOption::QStyleOption(int version, int type) : version(version), type(type), state(QStyle::State_None), - direction(QApplication::layoutDirection()), fontMetrics(QFont()) + direction(QApplication::layoutDirection()), fontMetrics(QFont()), styleObject(0) { } @@ -171,8 +170,8 @@ QStyleOption::~QStyleOption() \fn void QStyleOption::initFrom(const QWidget *widget) \since 4.1 - Initializes the \l state, \l direction, \l rect, \l palette, and - \l fontMetrics member variables based on the specified \a widget. + Initializes the \l state, \l direction, \l rect, \l palette, \l fontMetrics + and \l styleObject member variables based on the specified \a widget. This is a convenience function; the member variables can also be initialized manually. @@ -206,7 +205,8 @@ void QStyleOption::init(const QWidget *widget) extern bool qt_mac_can_clickThrough(const QWidget *w); //qwidget_mac.cpp if (!(state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget)) state &= ~QStyle::State_Enabled; - +#endif +#ifdef Q_OS_MAC switch (QMacStyle::widgetSizePolicy(widget)) { case QMacStyle::SizeSmall: state |= QStyle::State_Small; @@ -227,6 +227,7 @@ void QStyleOption::init(const QWidget *widget) rect = widget->rect(); palette = widget->palette(); fontMetrics = widget->fontMetrics(); + styleObject = const_cast<QWidget*>(widget); } /*! @@ -235,7 +236,7 @@ void QStyleOption::init(const QWidget *widget) QStyleOption::QStyleOption(const QStyleOption &other) : version(Version), type(Type), state(other.state), direction(other.direction), rect(other.rect), fontMetrics(other.fontMetrics), - palette(other.palette) + palette(other.palette), styleObject(other.styleObject) { } @@ -249,6 +250,7 @@ QStyleOption &QStyleOption::operator=(const QStyleOption &other) rect = other.rect; fontMetrics = other.fontMetrics; palette = other.palette; + styleObject = other.styleObject; return *this; } @@ -312,6 +314,15 @@ QStyleOption &QStyleOption::operator=(const QStyleOption &other) */ /*! + \variable QStyleOption::styleObject + \brief the object being styled + + The built-in styles support the following types: QWidget, QGraphicsObject and QQuickItem. + + \sa initFrom() +*/ + +/*! \variable QStyleOption::rect \brief the area that should be used for various calculations and painting @@ -1271,7 +1282,8 @@ QStyleOptionTab::QStyleOptionTab() row(0), position(Beginning), selectedPosition(NotAdjacent), cornerWidgets(QStyleOptionTab::NoCornerWidgets), - documentMode(false) + documentMode(false), + features(QStyleOptionTab::None) { } @@ -1284,7 +1296,8 @@ QStyleOptionTab::QStyleOptionTab(int version) row(0), position(Beginning), selectedPosition(NotAdjacent), cornerWidgets(QStyleOptionTab::NoCornerWidgets), - documentMode(false) + documentMode(false), + features(QStyleOptionTab::None) { } @@ -1438,6 +1451,17 @@ QStyleOptionTab::QStyleOptionTab(int version) */ /*! + \enum QStyleOptionTab::TabFeature + + Describes the various features that a tab button can have. + + \value None A normal tab button. + \value HasFrame The tab button is positioned on a tab frame + + \sa features +*/ + +/*! \variable QStyleOptionTab::leftButtonSize \brief the size for the left widget on the tab. @@ -4043,6 +4067,7 @@ QDebug operator<<(QDebug debug, const QStyleOption &option) debug << ',' << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight"); debug << ',' << option.state; debug << ',' << option.rect; + debug << ',' << option.styleObject; debug << ')'; #else Q_UNUSED(option); diff --git a/src/widgets/styles/qstyleoption.h b/src/widgets/styles/qstyleoption.h index 1f35ecb61f..d88582a9f8 100644 --- a/src/widgets/styles/qstyleoption.h +++ b/src/widgets/styles/qstyleoption.h @@ -89,6 +89,7 @@ public: QRect rect; QFontMetrics fontMetrics; QPalette palette; + QObject *styleObject; QStyleOption(int version = QStyleOption::Version, int type = SO_Default); QStyleOption(const QStyleOption &other); @@ -255,7 +256,9 @@ public: enum SelectedPosition { NotAdjacent, NextIsSelected, PreviousIsSelected }; enum CornerWidget { NoCornerWidgets = 0x00, LeftCornerWidget = 0x01, RightCornerWidget = 0x02 }; + enum TabFeature { None = 0x00, HasFrame = 0x01 }; Q_DECLARE_FLAGS(CornerWidgets, CornerWidget) + Q_DECLARE_FLAGS(TabFeatures, TabFeature) QTabBar::Shape shape; QString text; @@ -268,6 +271,7 @@ public: bool documentMode; QSize leftButtonSize; QSize rightButtonSize; + TabFeatures features; QStyleOptionTab(); QStyleOptionTab(const QStyleOptionTab &other) : QStyleOption(Version, Type) { *this = other; } diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 1cd9a98e87..857750b466 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -69,8 +69,8 @@ #include <qcheckbox.h> #include <qstatusbar.h> #include <qheaderview.h> -#include <qprogressbar.h> #include <private/qwindowsstyle_p.h> +#include <private/qstyleanimation_p.h> #include <qtabbar.h> #include <QMetaProperty> #include <qmainwindow.h> @@ -468,7 +468,7 @@ class QRenderRule { public: QRenderRule() : features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0) { } - QRenderRule(const QVector<QCss::Declaration> &, const QWidget *); + QRenderRule(const QVector<QCss::Declaration> &, const QObject *); ~QRenderRule() { } QRect borderRect(const QRect &r) const; @@ -859,7 +859,7 @@ static QStyle::StandardPixmap subControlIcon(int pe) return QStyle::SP_CustomBase; } -QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QWidget *widget) +QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QObject *object) : features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0) { QPalette palette = QApplication::palette(); // ###: ideally widget's palette @@ -928,7 +928,7 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QWidget hasFont = v.extractFont(&font, &adj); #ifndef QT_NO_TOOLTIP - if (widget && qstrcmp(widget->metaObject()->className(), "QTipLabel") == 0) + if (object && qstrcmp(object->metaObject()->className(), "QTipLabel") == 0) palette = QToolTip::palette(); #endif @@ -997,12 +997,15 @@ QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QWidget } } - if (widget) { + if (object) { QStyleSheetStyle *style = const_cast<QStyleSheetStyle *>(globalStyleSheetStyle); - if (!style) - style = qobject_cast<QStyleSheetStyle *>(widget->style()); - if (style) - fixupBorder(style->nativeFrameWidth(widget)); + if (!style) { + if (const QWidget *widget = qobject_cast<const QWidget *>(object)) { + style = qobject_cast<QStyleSheetStyle *>(widget->style()); + if (style) + fixupBorder(style->nativeFrameWidth(widget)); + } + } } if (hasBorder() && border()->hasBorderImage()) @@ -1407,14 +1410,14 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const Q // Style rules #define WIDGET(x) (static_cast<QWidget *>(x.ptr)) -static inline QWidget *parentWidget(const QWidget *w) +static inline QObject *parentObject(const QObject *obj) { - if(qobject_cast<const QLabel *>(w) && qstrcmp(w->metaObject()->className(), "QTipLabel") == 0) { - QWidget *p = qvariant_cast<QWidget *>(w->property("_q_stylesheet_parent")); + if (qobject_cast<const QLabel *>(obj) && qstrcmp(obj->metaObject()->className(), "QTipLabel") == 0) { + QObject *p = qvariant_cast<QObject *>(obj->property("_q_stylesheet_parent")); if (p) return p; } - return w->parentWidget(); + return obj->parent(); } class QStyleSheetStyleSelector : public StyleSelector @@ -1503,7 +1506,7 @@ public: bool isNullNode(NodePtr node) const { return node.ptr == 0; } NodePtr parentNode(NodePtr node) const - { NodePtr n; n.ptr = isNullNode(node) ? 0 : parentWidget(WIDGET(node)); return n; } + { NodePtr n; n.ptr = isNullNode(node) ? 0 : parentObject(WIDGET(node)); return n; } NodePtr previousSiblingNode(NodePtr) const { NodePtr n; n.ptr = 0; return n; } NodePtr duplicateNode(NodePtr node) const @@ -1515,13 +1518,13 @@ private: mutable QHash<const QWidget *, QHash<QString, QString> > m_attributeCache; }; -QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const +QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QObject *obj) const { - QHash<const QWidget *, QVector<StyleRule> >::const_iterator cacheIt = styleSheetCaches->styleRulesCache.constFind(w); + QHash<const QObject *, QVector<StyleRule> >::const_iterator cacheIt = styleSheetCaches->styleRulesCache.constFind(obj); if (cacheIt != styleSheetCaches->styleRulesCache.constEnd()) return cacheIt.value(); - if (!initWidget(w)) { + if (!initObject(obj)) { return QVector<StyleRule>(); } @@ -1558,36 +1561,37 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const styleSelector.styleSheets += appSs; } - QVector<QCss::StyleSheet> widgetSs; - for (const QWidget *wid = w; wid; wid = parentWidget(wid)) { - if (wid->styleSheet().isEmpty()) + QVector<QCss::StyleSheet> objectSs; + for (const QObject *o = obj; o; o = parentObject(o)) { + QString styleSheet = o->property("styleSheet").toString(); + if (styleSheet.isEmpty()) continue; StyleSheet ss; - QHash<const void *, StyleSheet>::const_iterator widCacheIt = styleSheetCaches->styleSheetCache.constFind(wid); - if (widCacheIt == styleSheetCaches->styleSheetCache.constEnd()) { - parser.init(wid->styleSheet()); + QHash<const void *, StyleSheet>::const_iterator objCacheIt = styleSheetCaches->styleSheetCache.constFind(o); + if (objCacheIt == styleSheetCaches->styleSheetCache.constEnd()) { + parser.init(styleSheet); if (!parser.parse(&ss)) { - parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1Char('}')); + parser.init(QLatin1String("* {") + styleSheet + QLatin1Char('}')); if (!parser.parse(&ss)) - qWarning("Could not parse stylesheet of widget %p", wid); + qWarning("Could not parse stylesheet of object %p", o); } ss.origin = StyleSheetOrigin_Inline; - styleSheetCaches->styleSheetCache.insert(wid, ss); + styleSheetCaches->styleSheetCache.insert(o, ss); } else { - ss = widCacheIt.value(); + ss = objCacheIt.value(); } - widgetSs.append(ss); + objectSs.append(ss); } - for (int i = 0; i < widgetSs.count(); i++) - widgetSs[i].depth = widgetSs.count() - i + 2; + for (int i = 0; i < objectSs.count(); i++) + objectSs[i].depth = objectSs.count() - i + 2; - styleSelector.styleSheets += widgetSs; + styleSelector.styleSheets += objectSs; StyleSelector::NodePtr n; - n.ptr = (void *)w; + n.ptr = (void *)obj; QVector<QCss::StyleRule> rules = styleSelector.styleRulesForNode(n); - styleSheetCaches->styleRulesCache.insert(w, rules); + styleSheetCaches->styleRulesCache.insert(obj, rules); return rules; } @@ -1696,36 +1700,36 @@ static quint64 pseudoClass(QStyle::State state) return pc; } -static void qt_check_if_internal_widget(const QWidget **w, int *element) +static void qt_check_if_internal_object(const QObject **obj, int *element) { #ifdef QT_NO_DOCKWIDGET - Q_UNUSED(w); + Q_UNUSED(obj); Q_UNUSED(element); #else - if (*w && qstrcmp((*w)->metaObject()->className(), "QDockWidgetTitleButton") == 0) { - if ((*w)->objectName() == QLatin1String("qt_dockwidget_closebutton")) { + if (*obj && qstrcmp((*obj)->metaObject()->className(), "QDockWidgetTitleButton") == 0) { + if ((*obj)->objectName() == QLatin1String("qt_dockwidget_closebutton")) { *element = PseudoElement_DockWidgetCloseButton; - } else if ((*w)->objectName() == QLatin1String("qt_dockwidget_floatbutton")) { + } else if ((*obj)->objectName() == QLatin1String("qt_dockwidget_floatbutton")) { *element = PseudoElement_DockWidgetFloatButton; } - *w = (*w)->parentWidget(); + *obj = (*obj)->parent(); } #endif } -QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, int element, quint64 state) const +QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, int element, quint64 state) const { - qt_check_if_internal_widget(&w, &element); - QHash<quint64, QRenderRule> &cache = styleSheetCaches->renderRulesCache[w][element]; + qt_check_if_internal_object(&obj, &element); + QHash<quint64, QRenderRule> &cache = styleSheetCaches->renderRulesCache[obj][element]; QHash<quint64, QRenderRule>::const_iterator cacheIt = cache.constFind(state); if (cacheIt != cache.constEnd()) return cacheIt.value(); - if (!initWidget(w)) + if (!initObject(obj)) return QRenderRule(); quint64 stateMask = 0; - const QVector<StyleRule> rules = styleRules(w); + const QVector<StyleRule> rules = styleRules(obj); for (int i = 0; i < rules.count(); i++) { const Selector& selector = rules.at(i).selectors.at(0); quint64 negated = 0; @@ -1743,14 +1747,14 @@ QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, int element, quint64 const QString part = QLatin1String(knownPseudoElements[element].name); QVector<Declaration> decls = declarations(rules, part, state); - QRenderRule newRule(decls, w); + QRenderRule newRule(decls, obj); cache[state] = newRule; if ((state & stateMask) != state) cache[state&stateMask] = newRule; return newRule; } -QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, const QStyleOption *opt, int pseudoElement) const +QRenderRule QStyleSheetStyle::renderRule(const QObject *obj, const QStyleOption *opt, int pseudoElement) const { quint64 extraClass = 0; QStyle::State state = opt ? opt->state : QStyle::State(QStyle::State_None); @@ -2006,7 +2010,7 @@ QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, const QStyleOption *o #endif #ifndef QT_NO_LINEEDIT // LineEdit sets Sunken flag to indicate Sunken frame (argh) - if (const QLineEdit *lineEdit = qobject_cast<const QLineEdit *>(w)) { + if (const QLineEdit *lineEdit = qobject_cast<const QLineEdit *>(obj)) { state &= ~QStyle::State_Sunken; if (lineEdit->hasFrame()) { extraClass &= ~PseudoClass_Frameless; @@ -2015,29 +2019,29 @@ QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, const QStyleOption *o } } else #endif - if (const QFrame *frm = qobject_cast<const QFrame *>(w)) { + if (const QFrame *frm = qobject_cast<const QFrame *>(obj)) { if (frm->lineWidth() == 0) extraClass |= PseudoClass_Frameless; } } - return renderRule(w, pseudoElement, pseudoClass(state) | extraClass); + return renderRule(obj, pseudoElement, pseudoClass(state) | extraClass); } -bool QStyleSheetStyle::hasStyleRule(const QWidget *w, int part) const +bool QStyleSheetStyle::hasStyleRule(const QObject *obj, int part) const { - QHash<int, bool> &cache = styleSheetCaches->hasStyleRuleCache[w]; + QHash<int, bool> &cache = styleSheetCaches->hasStyleRuleCache[obj]; QHash<int, bool>::const_iterator cacheIt = cache.constFind(part); if (cacheIt != cache.constEnd()) return cacheIt.value(); - if (!initWidget(w)) + if (!initObject(obj)) return false; - const QVector<StyleRule> &rules = styleRules(w); + const QVector<StyleRule> &rules = styleRules(obj); if (part == PseudoElement_None) { - bool result = w && !rules.isEmpty(); + bool result = obj && !rules.isEmpty(); cache[part] = result; return result; } @@ -2594,25 +2598,24 @@ void QStyleSheetStyle::unsetPalette(QWidget *w) } } -static void updateWidgets(const QList<const QWidget *>& widgets) +static void updateObjects(const QList<const QObject *>& objects) { if (!styleSheetCaches->styleRulesCache.isEmpty() || !styleSheetCaches->hasStyleRuleCache.isEmpty() || !styleSheetCaches->renderRulesCache.isEmpty()) { - for (int i = 0; i < widgets.size(); ++i) { - const QWidget *widget = widgets.at(i); - styleSheetCaches->styleRulesCache.remove(widget); - styleSheetCaches->hasStyleRuleCache.remove(widget); - styleSheetCaches->renderRulesCache.remove(widget); + for (int i = 0; i < objects.size(); ++i) { + const QObject *object = objects.at(i); + styleSheetCaches->styleRulesCache.remove(object); + styleSheetCaches->hasStyleRuleCache.remove(object); + styleSheetCaches->renderRulesCache.remove(object); } } - for (int i = 0; i < widgets.size(); ++i) { - QWidget *widget = const_cast<QWidget *>(widgets.at(i)); - if (widget == 0) + for (int i = 0; i < objects.size(); ++i) { + QObject *object = const_cast<QObject *>(objects.at(i)); + if (object == 0) continue; - widget->style()->polish(widget); + if (QWidget *widget = qobject_cast<QWidget *>(object)) + widget->style()->polish(widget); QEvent event(QEvent::StyleChange); - QApplication::sendEvent(widget, &event); - widget->update(); - widget->updateGeometry(); + QApplication::sendEvent(object, &event); } } @@ -2645,13 +2648,13 @@ QStyle *QStyleSheetStyle::baseStyle() const return QApplication::style(); } -void QStyleSheetStyleCaches::widgetDestroyed(QObject *o) +void QStyleSheetStyleCaches::objectDestroyed(QObject *o) { - styleRulesCache.remove((const QWidget *)o); - hasStyleRuleCache.remove((const QWidget *)o); - renderRulesCache.remove((const QWidget *)o); + styleRulesCache.remove(o); + hasStyleRuleCache.remove(o); + renderRulesCache.remove(o); customPaletteWidgets.remove((const QWidget *)o); - styleSheetCache.remove((const QWidget *)o); + styleSheetCache.remove(o); autoFillDisabledWidgets.remove((const QWidget *)o); } @@ -2664,18 +2667,19 @@ void QStyleSheetStyleCaches::styleDestroyed(QObject *o) * Make sure that the cache will be clean by connecting destroyed if needed. * return false if the widget is not stylable; */ -bool QStyleSheetStyle::initWidget(const QWidget *w) const +bool QStyleSheetStyle::initObject(const QObject *obj) const { - if (!w) - return false; - if(w->testAttribute(Qt::WA_StyleSheet)) - return true; - - if(unstylable(w)) + if (!obj) return false; + if (const QWidget *w = qobject_cast<const QWidget*>(obj)) { + if (w->testAttribute(Qt::WA_StyleSheet)) + return true; + if (unstylable(w)) + return false; + const_cast<QWidget *>(w)->setAttribute(Qt::WA_StyleSheet, true); + } - const_cast<QWidget *>(w)->setAttribute(Qt::WA_StyleSheet, true); - QObject::connect(w, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(widgetDestroyed(QObject*)), Qt::UniqueConnection); + QObject::connect(obj, SIGNAL(destroyed(QObject*)), styleSheetCaches, SLOT(objectDestroyed(QObject*)), Qt::UniqueConnection); return true; } @@ -2684,7 +2688,7 @@ void QStyleSheetStyle::polish(QWidget *w) baseStyle()->polish(w); RECURSION_GUARD(return) - if (!initWidget(w)) + if (!initObject(w)) return; if (styleSheetCaches->styleRulesCache.contains(w)) { @@ -2725,12 +2729,6 @@ void QStyleSheetStyle::polish(QWidget *w) } #endif -#ifndef QT_NO_PROGRESSBAR - if (QProgressBar *pb = qobject_cast<QProgressBar *>(w)) { - QWindowsStyle::polish(pb); - } -#endif - QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Any); if (rule.hasDrawable() || rule.hasBox()) { if (w->metaObject() == &QWidget::staticMetaObject @@ -2782,21 +2780,21 @@ void QStyleSheetStyle::polish(QPalette &pal) void QStyleSheetStyle::repolish(QWidget *w) { - QList<const QWidget *> children = w->findChildren<const QWidget *>(QString()); + QList<const QObject *> children = w->findChildren<const QObject *>(QString()); children.append(w); styleSheetCaches->styleSheetCache.remove(w); - updateWidgets(children); + updateObjects(children); } void QStyleSheetStyle::repolish(QApplication *app) { Q_UNUSED(app); - const QList<const QWidget*> allWidgets = styleSheetCaches->styleRulesCache.keys(); + const QList<const QObject*> allObjects = styleSheetCaches->styleRulesCache.keys(); styleSheetCaches->styleSheetCache.remove(qApp); styleSheetCaches->styleRulesCache.clear(); styleSheetCaches->hasStyleRuleCache.clear(); styleSheetCaches->renderRulesCache.clear(); - updateWidgets(allWidgets); + updateObjects(allObjects); } void QStyleSheetStyle::unpolish(QWidget *w) @@ -2825,10 +2823,6 @@ void QStyleSheetStyle::unpolish(QWidget *w) sa, SLOT(update())); } #endif -#ifndef QT_NO_PROGRESSBAR - if (QProgressBar *pb = qobject_cast<QProgressBar *>(w)) - QWindowsStyle::unpolish(pb); -#endif baseStyle()->unpolish(w); } @@ -3829,10 +3823,14 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q } QRect r = rect; + Q_D(const QWindowsStyle); if (pb->minimum == 0 && pb->maximum == 0) { - Q_D(const QWindowsStyle); int chunkCount = fillWidth/chunkWidth; - int offset = (d->animateStep*8%rect.width()); + int offset = 0; + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject))) + offset = animation->animationStep() * 8 % rect.width(); + else + d->startAnimation(new QProgressStyleAnimation(d->animationFps, opt->styleObject)); int x = reverse ? r.left() + r.width() - offset - chunkWidth : r.x() + offset; while (chunkCount > 0) { r.setRect(x, rect.y(), chunkWidth, rect.height()); @@ -3863,6 +3861,8 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q subRule.drawRule(p, r); x += reverse ? -chunkWidth : chunkWidth; } + + d->stopAnimation(opt->styleObject); } p->restore(); @@ -5874,9 +5874,9 @@ Qt::Alignment QStyleSheetStyle::resolveAlignment(Qt::LayoutDirection layDir, Qt: // This does not mean that any QTabBar which is a child of QTabWidget will // match, only the one that was created by the QTabWidget initialization // (and hence has the correct object name). -bool QStyleSheetStyle::isNaturalChild(const QWidget *w) +bool QStyleSheetStyle::isNaturalChild(const QObject *obj) { - if (w->objectName().startsWith(QLatin1String("qt_"))) + if (obj->objectName().startsWith(QLatin1String("qt_"))) return true; return false; diff --git a/src/widgets/styles/qstylesheetstyle_p.h b/src/widgets/styles/qstylesheetstyle_p.h index 93bb4441bb..f42c0e9b20 100644 --- a/src/widgets/styles/qstylesheetstyle_p.h +++ b/src/widgets/styles/qstylesheetstyle_p.h @@ -143,8 +143,8 @@ private: friend class QRenderRule; int nativeFrameWidth(const QWidget *); - QRenderRule renderRule(const QWidget *, int, quint64 = 0) const; - QRenderRule renderRule(const QWidget *, const QStyleOption *, int = 0) const; + QRenderRule renderRule(const QObject *, int, quint64 = 0) const; + QRenderRule renderRule(const QObject *, const QStyleOption *, int = 0) const; QSize defaultSize(const QWidget *, QSize, const QRect&, int) const; QRect positionRect(const QWidget *, const QRenderRule&, const QRenderRule&, int, const QRect&, Qt::LayoutDirection) const; @@ -157,16 +157,16 @@ private: void unsetPalette(QWidget *); void setProperties(QWidget *); void setGeometry(QWidget *); - QVector<QCss::StyleRule> styleRules(const QWidget *w) const; - bool hasStyleRule(const QWidget *w, int part) const; + QVector<QCss::StyleRule> styleRules(const QObject *obj) const; + bool hasStyleRule(const QObject *obj, int part) const; QHash<QStyle::SubControl, QRect> titleBarLayout(const QWidget *w, const QStyleOptionTitleBar *tb) const; QCss::StyleSheet getDefaultStyleSheet() const; static Qt::Alignment resolveAlignment(Qt::LayoutDirection, Qt::Alignment); - static bool isNaturalChild(const QWidget *w); - bool initWidget(const QWidget *w) const; + static bool isNaturalChild(const QObject *obj); + bool initObject(const QObject *obj) const; public: static int numinstances; @@ -179,13 +179,13 @@ class QStyleSheetStyleCaches : public QObject { Q_OBJECT public Q_SLOTS: - void widgetDestroyed(QObject *); + void objectDestroyed(QObject *); void styleDestroyed(QObject *); public: - QHash<const QWidget *, QVector<QCss::StyleRule> > styleRulesCache; - QHash<const QWidget *, QHash<int, bool> > hasStyleRuleCache; + QHash<const QObject *, QVector<QCss::StyleRule> > styleRulesCache; + QHash<const QObject *, QHash<int, bool> > hasStyleRuleCache; typedef QHash<int, QHash<quint64, QRenderRule> > QRenderRules; - QHash<const QWidget *, QRenderRules> renderRulesCache; + QHash<const QObject *, QRenderRules> renderRulesCache; QHash<const QWidget *, QPalette> customPaletteWidgets; // widgets whose palette we tampered QHash<const void *, QCss::StyleSheet> styleSheetCache; // parsed style sheets QSet<const QWidget *> autoFillDisabledWidgets; diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 355ecf8a35..9e5e65dcc1 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -54,7 +54,6 @@ #include <private/qmenubar_p.h> #include "qpaintengine.h" #include "qpainter.h" -#include "qprogressbar.h" #include "qrubberband.h" #include "qstyleoption.h" #include "qtabbar.h" @@ -68,8 +67,11 @@ #include "qlistview.h" #include <private/qmath_p.h> #include <qmath.h> +#include <qpa/qplatformtheme.h> +#include <private/qguiapplication_p.h> #include <private/qstylehelper_p.h> +#include <private/qstyleanimation_p.h> QT_BEGIN_NAMESPACE @@ -117,7 +119,7 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; \internal */ QWindowsStylePrivate::QWindowsStylePrivate() - : alt_down(false), menuBarTimer(0), animationFps(10), animateTimer(0), animateStep(0) + : alt_down(false), menuBarTimer(0) { #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA @@ -126,27 +128,6 @@ QWindowsStylePrivate::QWindowsStylePrivate() pSHGetStockIconInfo = (PtrSHGetStockIconInfo)shellLib.resolve("SHGetStockIconInfo"); } #endif - startTime.start(); -} - -void QWindowsStylePrivate::startAnimation(QObject *o, QProgressBar *bar) -{ - if (!animatedProgressBars.contains(bar)) { - animatedProgressBars << bar; - if (!animateTimer) { - Q_ASSERT(animationFps > 0); - animateTimer = o->startTimer(1000 / animationFps); - } - } -} - -void QWindowsStylePrivate::stopAnimation(QObject *o, QProgressBar *bar) -{ - animatedProgressBars.removeAll(bar); - if (animatedProgressBars.isEmpty() && animateTimer) { - o->killTimer(animateTimer); - animateTimer = 0; - } } // Returns true if the toplevel parent of \a widget has seen the Alt-key @@ -159,23 +140,6 @@ bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const /*! \reimp */ -void QWindowsStyle::timerEvent(QTimerEvent *event) -{ -#ifndef QT_NO_PROGRESSBAR - Q_D(QWindowsStyle); - if (event->timerId() == d->animateTimer) { - Q_ASSERT(d->animationFps> 0); - d->animateStep = d->startTime.elapsed() / (1000 / d->animationFps); - foreach (QProgressBar *bar, d->animatedProgressBars) - bar->update(); - } -#endif // QT_NO_PROGRESSBAR - event->ignore(); -} - -/*! - \reimp -*/ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) { // Records Alt- and Focus events @@ -224,27 +188,6 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) d->seenAlt.removeAll(widget); d->seenAlt.removeAll(widget->window()); break; -#ifndef QT_NO_PROGRESSBAR - case QEvent::StyleChange: - case QEvent::Paint: - case QEvent::Show: - if (QProgressBar *bar = qobject_cast<QProgressBar *>(o)) { - // Animation by timer for progress bars that have their min and - // max values the same - if (bar->minimum() == bar->maximum()) - d->startAnimation(this, bar); - else - d->stopAnimation(this, bar); - } - break; - case QEvent::Destroy: - case QEvent::Hide: - // Do static_cast because there is no type info when getting - // the destroy event. We know that it is a QProgressBar, since - // we only install a widget event filter for QScrollBars. - d->stopAnimation(this, static_cast<QProgressBar *>(o)); - break; -#endif // QT_NO_PROGRESSBAR default: break; } @@ -335,23 +278,12 @@ void QWindowsStyle::unpolish(QApplication *app) void QWindowsStyle::polish(QWidget *widget) { QCommonStyle::polish(widget); -#ifndef QT_NO_PROGRESSBAR - if (qobject_cast<QProgressBar *>(widget)) - widget->installEventFilter(this); -#endif } /*! \reimp */ void QWindowsStyle::unpolish(QWidget *widget) { QCommonStyle::unpolish(widget); -#ifndef QT_NO_PROGRESSBAR - if (QProgressBar *bar=qobject_cast<QProgressBar *>(widget)) { - Q_D(QWindowsStyle); - widget->removeEventFilter(this); - d->stopAnimation(this, bar); - } -#endif } /*! @@ -911,26 +843,6 @@ static const char *const question_xpm[] = { #endif //QT_NO_IMAGEFORMAT_XPM -#ifdef Q_OS_WIN -static QPixmap loadIconFromShell32( int resourceId, int size ) -{ -#ifdef Q_OS_WINCE - HMODULE hmod = LoadLibrary(L"ceshell"); -#else - HMODULE hmod = QSystemLibrary::load(L"shell32"); -#endif - if( hmod ) { - HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0); - if( iconHandle ) { - QPixmap iconpixmap = qt_pixmapFromWinHICON(iconHandle); - DestroyIcon(iconHandle); - return iconpixmap; - } - } - return QPixmap(); -} -#endif - /*! \reimp */ @@ -942,125 +854,32 @@ QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyl switch(standardPixmap) { case SP_DriveCDIcon: case SP_DriveDVDIcon: - { - desktopIcon = loadIconFromShell32(12, 16); - break; - } case SP_DriveNetIcon: - { - desktopIcon = loadIconFromShell32(10, 16); - break; - } case SP_DriveHDIcon: - { - desktopIcon = loadIconFromShell32(9, 16); - break; - } case SP_DriveFDIcon: - { - desktopIcon = loadIconFromShell32(7, 16); - break; - } case SP_FileIcon: - { - desktopIcon = loadIconFromShell32(1, 16); - break; - } case SP_FileLinkIcon: - { - desktopIcon = loadIconFromShell32(1, 16); - QPainter painter(&desktopIcon); - QPixmap link = loadIconFromShell32(30, 16); - painter.drawPixmap(0, 0, 16, 16, link); - break; - } case SP_DirLinkIcon: - { - desktopIcon = loadIconFromShell32(4, 16); - QPainter painter(&desktopIcon); - QPixmap link = loadIconFromShell32(30, 16); - painter.drawPixmap(0, 0, 16, 16, link); - break; - } case SP_DirClosedIcon: - { - desktopIcon = loadIconFromShell32(4, 16); - break; - } case SP_DesktopIcon: - { - desktopIcon = loadIconFromShell32(35, 16); - break; - } case SP_ComputerIcon: - { - desktopIcon = loadIconFromShell32(16, 16); - break; - } case SP_DirOpenIcon: - { - desktopIcon = loadIconFromShell32(5, 16); - break; - } case SP_FileDialogNewFolder: - { - desktopIcon = loadIconFromShell32(319, 16); - break; - } case SP_DirHomeIcon: - { - desktopIcon = loadIconFromShell32(235, 16); - break; - } case SP_TrashIcon: - { - desktopIcon = loadIconFromShell32(191, 16); - break; + case SP_VistaShield: + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardPixmap); + desktopIcon = theme->standardPixmap(sp, QSizeF(16, 16)); } + break; case SP_MessageBoxInformation: - { - HICON iconHandle = LoadIcon(NULL, IDI_INFORMATION); - desktopIcon = qt_pixmapFromWinHICON(iconHandle); - DestroyIcon(iconHandle); - break; - } case SP_MessageBoxWarning: - { - HICON iconHandle = LoadIcon(NULL, IDI_WARNING); - desktopIcon = qt_pixmapFromWinHICON(iconHandle); - DestroyIcon(iconHandle); - break; - } case SP_MessageBoxCritical: - { - HICON iconHandle = LoadIcon(NULL, IDI_ERROR); - desktopIcon = qt_pixmapFromWinHICON(iconHandle); - DestroyIcon(iconHandle); - break; - } case SP_MessageBoxQuestion: - { - HICON iconHandle = LoadIcon(NULL, IDI_QUESTION); - desktopIcon = qt_pixmapFromWinHICON(iconHandle); - DestroyIcon(iconHandle); - break; - } - case SP_VistaShield: - { - if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA - && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) - && pSHGetStockIconInfo) - { - QPixmap pixmap; - QSHSTOCKICONINFO iconInfo; - memset(&iconInfo, 0, sizeof(iconInfo)); - iconInfo.cbSize = sizeof(iconInfo); - if (pSHGetStockIconInfo(_SIID_SHIELD, _SHGFI_ICON | _SHGFI_SMALLICON, &iconInfo) == S_OK) { - pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon); - DestroyIcon(iconInfo.hIcon); - return pixmap; - } - } + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardPixmap); + desktopIcon = theme->standardPixmap(sp, QSizeF()); } break; default: @@ -1424,6 +1243,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, imagePainter.translate(sx + bsx, sy + bsy); imagePainter.setPen(opt->palette.buttonText().color()); imagePainter.setBrush(opt->palette.buttonText()); + imagePainter.setRenderHint(QPainter::Qt4CompatiblePainting); if (!(opt->state & State_Enabled)) { imagePainter.translate(1, 1); @@ -1562,6 +1382,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, } p->save(); + p->setRenderHint(QPainter::Qt4CompatiblePainting); bool down = opt->state & State_Sunken; bool enabled = opt->state & State_Enabled; bool on = opt->state & State_On; @@ -1640,41 +1461,6 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, } break; #endif // QT_NO_FRAME - case PE_IndicatorBranch: { - // This is _way_ too similar to the common style. - static const int decoration_size = 9; - int mid_h = opt->rect.x() + opt->rect.width() / 2; - int mid_v = opt->rect.y() + opt->rect.height() / 2; - int bef_h = mid_h; - int bef_v = mid_v; - int aft_h = mid_h; - int aft_v = mid_v; - if (opt->state & State_Children) { - int delta = decoration_size / 2; - bef_h -= delta; - bef_v -= delta; - aft_h += delta; - aft_v += delta; - p->drawLine(bef_h + 2, bef_v + 4, bef_h + 6, bef_v + 4); - if (!(opt->state & State_Open)) - p->drawLine(bef_h + 4, bef_v + 2, bef_h + 4, bef_v + 6); - QPen oldPen = p->pen(); - p->setPen(opt->palette.dark().color()); - p->drawRect(bef_h, bef_v, decoration_size - 1, decoration_size - 1); - p->setPen(oldPen); - } - QBrush brush(opt->palette.dark().color(), Qt::Dense4Pattern); - if (opt->state & State_Item) { - if (opt->direction == Qt::RightToLeft) - p->fillRect(opt->rect.left(), mid_v, bef_h - opt->rect.left(), 1, brush); - else - p->fillRect(aft_h, mid_v, opt->rect.right() - aft_h + 1, 1, brush); - } - if (opt->state & State_Sibling) - p->fillRect(mid_h, aft_v, 1, opt->rect.bottom() - aft_v + 1, brush); - if (opt->state & (State_Open | State_Children | State_Item | State_Sibling)) - p->fillRect(mid_h, opt->rect.y(), 1, bef_v - opt->rect.y(), brush); - break; } case PE_FrameButtonBevel: case PE_PanelButtonBevel: { QBrush fill; @@ -1715,7 +1501,6 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, qDrawShadePanel(p, opt->rect, opt->palette, true, 1, 0); break; -#ifndef QT_NO_PROGRESSBAR case PE_IndicatorProgressChunk: { bool vertical = false, inverted = false; @@ -1749,7 +1534,6 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, } } break; -#endif // QT_NO_PROGRESSBAR case PE_FrameTabWidget: { qDrawWinButton(p, opt->rect, opt->palette, false, 0); @@ -2365,7 +2149,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai #endif // QT_NO_TOOLBAR -#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) { QRect rect = pb->rect; @@ -2396,8 +2180,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai if (inverted) reverse = !reverse; int w = rect.width(); + Q_D(const QWindowsStyle); if (pb->minimum == 0 && pb->maximum == 0) { - Q_D(const QWindowsStyle); const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget); QStyleOptionProgressBarV2 pbBits = *pb; Q_ASSERT(unit_width >0); @@ -2405,8 +2189,12 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai pbBits.rect = rect; pbBits.palette = pal2; + int step = 0; int chunkCount = w / unit_width + 1; - int step = d->animateStep%chunkCount; + if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject))) + step = (animation->animationStep() / 3) % chunkCount; + else + d->startAnimation(new QProgressStyleAnimation(d->animationFps, opt->styleObject)); int chunksInRow = 5; int myY = pbBits.rect.y(); int myHeight = pbBits.rect.height(); @@ -2440,11 +2228,11 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai p->restore(); //restore state } else { + d->stopAnimation(opt->styleObject); QCommonStyle::drawControl(ce, opt, p, widget); } } break; -#endif // QT_NO_PROGRESSBAR #ifndef QT_NO_DOCKWIDGET case CE_DockWidgetTitle: @@ -2701,8 +2489,10 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp } QBrush oldBrush = p->brush(); + bool oldQt4CompatiblePainting = p->testRenderHint(QPainter::Qt4CompatiblePainting); p->setPen(Qt::NoPen); p->setBrush(handleBrush); + p->setRenderHint(QPainter::Qt4CompatiblePainting); Qt::BGMode oldMode = p->backgroundMode(); p->setBackgroundMode(Qt::OpaqueMode); p->drawRect(x1, y1, x2-x1+1, y2-y1+1); @@ -2785,6 +2575,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp p->drawLine(x2, y2-1, x2+d, y2-1-d); break; } + p->setRenderHint(QPainter::Qt4CompatiblePainting, oldQt4CompatiblePainting); } } break; @@ -3064,124 +2855,47 @@ QIcon QWindowsStyle::standardIcon(StandardPixmap standardIcon, const QStyleOptio const QWidget *widget) const { QIcon icon; - QPixmap pixmap; #ifdef Q_OS_WIN + QPixmap pixmap; switch (standardIcon) { - case SP_FileDialogNewFolder: - { - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(319, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; - } - case SP_DirHomeIcon: - { - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(235, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; - } - case SP_DirIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(4, size); - icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); - pixmap = loadIconFromShell32(5, size); - icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); - } - break; - case SP_DirLinkIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - QPixmap link = loadIconFromShell32(30, size); - pixmap = loadIconFromShell32(4, size); - if (!pixmap.isNull() && !link.isNull()) { - QPainter painter(&pixmap); - painter.drawPixmap(0, 0, size, size, link); - icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); - } - link = loadIconFromShell32(30, size); - pixmap = loadIconFromShell32(5, size); - if (!pixmap.isNull() && !link.isNull()) { - QPainter painter(&pixmap); - painter.drawPixmap(0, 0, size, size, link); - icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); - } - } - break; - case SP_FileIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(1, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; - case SP_ComputerIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(16, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; - - case SP_DesktopIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(35, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; case SP_DriveCDIcon: case SP_DriveDVDIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(12, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; case SP_DriveNetIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(10, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; case SP_DriveHDIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(9, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; case SP_DriveFDIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - pixmap = loadIconFromShell32(7, size); - icon.addPixmap(pixmap, QIcon::Normal); - } - break; + case SP_FileIcon: case SP_FileLinkIcon: - for (int size = 16 ; size <= 32 ; size += 16) { - QPixmap link; - link = loadIconFromShell32(30, size); - pixmap = loadIconFromShell32(1, size); - if (!pixmap.isNull() && !link.isNull()) { - QPainter painter(&pixmap); - painter.drawPixmap(0, 0, size, size, link); + case SP_DesktopIcon: + case SP_ComputerIcon: + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon); + for (int size = 16 ; size <= 32 ; size += 16) { + pixmap = theme->standardPixmap(sp, QSizeF(size, size)); icon.addPixmap(pixmap, QIcon::Normal); } } break; - case SP_VistaShield: - { - if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA - && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) - && pSHGetStockIconInfo) - { - icon.addPixmap(proxy()->standardPixmap(SP_VistaShield, option, widget)); //fetches small icon - QSHSTOCKICONINFO iconInfo; //append large icon - memset(&iconInfo, 0, sizeof(iconInfo)); - iconInfo.cbSize = sizeof(iconInfo); - if (pSHGetStockIconInfo(_SIID_SHIELD, _SHGFI_ICON | _SHGFI_LARGEICON, &iconInfo) == S_OK) { - icon.addPixmap(qt_pixmapFromWinHICON(iconInfo.hIcon)); - DestroyIcon(iconInfo.hIcon); - } + case SP_DirIcon: + case SP_DirLinkIcon: + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + QPlatformTheme::StandardPixmap spOff = static_cast<QPlatformTheme::StandardPixmap>(standardIcon); + QPlatformTheme::StandardPixmap spOn = standardIcon == SP_DirIcon ? QPlatformTheme::DirOpenIcon : + QPlatformTheme::DirLinkOpenIcon; + for (int size = 16 ; size <= 32 ; size += 16) { + QSizeF pixSize(size, size); + pixmap = theme->standardPixmap(spOff, pixSize); + icon.addPixmap(pixmap, QIcon::Normal, QIcon::Off); + pixmap = theme->standardPixmap(spOn, pixSize); + icon.addPixmap(pixmap, QIcon::Normal, QIcon::On); } } break; + case SP_VistaShield: + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + QPlatformTheme::StandardPixmap sp = static_cast<QPlatformTheme::StandardPixmap>(standardIcon); + pixmap = theme->standardPixmap(sp, QSizeF(32, 32)); + } + break; default: break; } diff --git a/src/widgets/styles/qwindowsstyle.h b/src/widgets/styles/qwindowsstyle.h index cacaeaa301..1d9347a72e 100644 --- a/src/widgets/styles/qwindowsstyle.h +++ b/src/widgets/styles/qwindowsstyle.h @@ -91,7 +91,6 @@ public: protected: bool eventFilter(QObject *o, QEvent *e); - void timerEvent(QTimerEvent *event); QWindowsStyle(QWindowsStylePrivate &dd); private: diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h index 0cf53b9903..6d69557edd 100644 --- a/src/widgets/styles/qwindowsstyle_p.h +++ b/src/widgets/styles/qwindowsstyle_p.h @@ -59,31 +59,22 @@ #ifndef QT_NO_STYLE_WINDOWS #include <qlist.h> #include <qhash.h> -#include <qelapsedtimer.h> QT_BEGIN_NAMESPACE class QTime; -class QProgressBar; class QWindowsStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QWindowsStyle) public: QWindowsStylePrivate(); - void startAnimation(QObject *o, QProgressBar *bar); - void stopAnimation(QObject *o, QProgressBar *bar); bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } bool alt_down; QList<const QWidget *> seenAlt; int menuBarTimer; - QList<QProgressBar *> animatedProgressBars; - int animationFps; - int animateTimer; - QElapsedTimer startTime; - int animateStep; QColor inactiveCaptionText; QColor activeCaptionColor; QColor activeGradientCaptionColor; diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index cb34a20fa3..d8bf6920ac 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -43,6 +43,7 @@ #include "qwindowsvistastyle_p.h" #include <qscreen.h> #include <qwindow.h> +#include <private/qstyleanimation_p.h> #include <private/qstylehelper_p.h> #include <private/qsystemlibrary_p.h> #include <private/qapplication_p.h> @@ -202,6 +203,11 @@ void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option Q_UNUSED(painter); } +bool QWindowsVistaAnimation::isUpdateNeeded() const +{ + return QWindowsVistaStylePrivate::useVista(); +} + /*! \internal Helperfunction to paint the current transition state between two @@ -255,7 +261,7 @@ void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, flo /*! \internal Paints a transition state. The result will be a mix between the initial and final state of the transition, depending on the time - difference between _startTime and current time. + difference between startTime and current time. */ void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option) { @@ -263,18 +269,18 @@ void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *optio if (_duration > 0) { QTime current = QTime::currentTime(); - if (_startTime > current) - _startTime = current; + if (startTime() > current) + setStartTime(current); - int timeDiff = _startTime.msecsTo(current); + int timeDiff = startTime().msecsTo(current); alpha = timeDiff/(float)_duration; if (timeDiff > _duration) { - _running = false; + stop(); alpha = 1.0; } } else { - _running = false; + stop(); } drawBlendedImage(painter, option->rect, alpha); } @@ -282,7 +288,7 @@ void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *optio /*! \internal Paints a pulse. The result will be a mix between the primary and secondary pulse images depending on the time difference between - _startTime and current time. + startTime and current time. */ void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option) { @@ -290,15 +296,15 @@ void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option) if (_duration > 0) { QTime current = QTime::currentTime(); - if (_startTime > current) - _startTime = current; + if (startTime() > current) + setStartTime(current); - int timeDiff = _startTime.msecsTo(current) % _duration*2; + int timeDiff = startTime().msecsTo(current) % _duration*2; if (timeDiff > _duration) timeDiff = _duration*2 - timeDiff; alpha = timeDiff/(float)_duration; } else { - _running = false; + stop(); } drawBlendedImage(painter, option->rect, alpha); } @@ -341,6 +347,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt int state = option->state; if (!QWindowsVistaStylePrivate::useVista()) { + foreach (const QObject *target, d->animationTargets()) + d->stopAnimation(target); QWindowsStyle::drawPrimitive(element, option, painter, widget); return; } @@ -399,9 +407,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt startImage.fill(0); QPainter startPainter(&startImage); - QWindowsVistaAnimation *anim = d->widgetAnimation(widget); - QWindowsVistaTransition *t = new QWindowsVistaTransition; - t->setWidget(w); + QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)); + QWindowsVistaTransition *t = new QWindowsVistaTransition(w); // If we have a running animation on the widget already, we will use that to paint the initial // state of the new transition, this ensures a smooth transition from a current animation such as a @@ -539,7 +546,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt case PE_IndicatorCheckBox: case PE_IndicatorRadioButton: { - if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *a = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)) ){ a->paint(painter, option); } else { QWindowsXPStyle::drawPrimitive(element, option, painter, widget); @@ -655,7 +662,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt break; case PE_FrameLineEdit: - if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget))) { anim->paint(painter, option); } else { QPainter *p = painter; @@ -903,6 +910,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func()); if (!QWindowsVistaStylePrivate::useVista()) { + foreach (const QObject *target, d->animationTargets()) + d->stopAnimation(target); QWindowsStyle::drawControl(element, option, painter, widget); return; } @@ -950,14 +959,13 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (doTransition) { QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)); QStyleOptionButton opt = *button; opt.state = (QStyle::State)oldState; startImage.fill(0); - QWindowsVistaTransition *t = new QWindowsVistaTransition; - t->setWidget(w); + QWindowsVistaTransition *t = new QWindowsVistaTransition(w); QPainter startPainter(&startImage); if (!anim) { @@ -992,7 +1000,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption case CE_PushButtonBevel: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { - QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)); if (anim && (btn->state & State_Enabled)) { anim->paint(painter, option); } else { @@ -1026,8 +1034,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); alternateImage.fill(0); - QWindowsVistaPulse *pulse = new QWindowsVistaPulse; - pulse->setWidget(const_cast<QWidget*>(widget)); + QWindowsVistaPulse *pulse = new QWindowsVistaPulse(const_cast<QWidget*>(widget)); QPainter startPainter(&startImage); stateId = PBS_DEFAULTED; @@ -1082,7 +1089,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption return; } break; -#ifndef QT_NO_PROGRESSBAR + case CE_ProgressBarContents: if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { @@ -1094,17 +1101,11 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption inverted = pb2->invertedAppearance; } - if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) { - if (isIndeterminate || (progressbar->value() > 0 && (progressbar->value() < progressbar->maximum()) && d->transitionsEnabled())) { - if (!d->widgetAnimation(progressbar)) { - QWindowsVistaAnimation *a = new QWindowsVistaAnimation; - a->setWidget(const_cast<QWidget*>(widget)); - a->setStartTime(QTime::currentTime()); - d->startAnimation(a); - } - } else { - d->stopAnimation(progressbar); - } + if (isIndeterminate || (bar->progress > 0 && (bar->progress < bar->maximum) && d->transitionsEnabled())) { + if (!d->animation(option->styleObject)) + d->startAnimation(new QProgressStyleAnimation(d->animationFps, option->styleObject)); + } else { + d->stopAnimation(option->styleObject); } XPThemeData theme(widget, painter, @@ -1115,7 +1116,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QTime current = QTime::currentTime(); if (isIndeterminate) { - if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { + if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(option->styleObject))) { int glowSize = 120; int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animOffset = a->startTime().msecsTo(current) / 4; @@ -1185,7 +1186,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } d->drawBackground(theme); - if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { + if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(option->styleObject))) { int glowSize = 140; int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animOffset = a->startTime().msecsTo(current) / 4; @@ -1194,8 +1195,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (bar->progress < bar->maximum) a->setStartTime(QTime::currentTime()); else - d->stopAnimation(widget); //we stop the glow motion only after it has - //moved out of view + d->stopAnimation(option->styleObject); //we stop the glow motion only after it has + //moved out of view } painter->save(); painter->setClipRect(theme.rect); @@ -1214,7 +1215,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } } break; -#endif // QT_NO_PROGRESSBAR + case CE_MenuBarItem: { @@ -1574,6 +1575,8 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle { QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func()); if (!QWindowsVistaStylePrivate::useVista()) { + foreach (const QObject *target, d->animationTargets()) + d->stopAnimation(target); QWindowsStyle::drawComplexControl(control, option, painter, widget); return; } @@ -1636,9 +1639,8 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle if (doTransition) { QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - QWindowsVistaAnimation *anim = d->widgetAnimation(widget); - QWindowsVistaTransition *t = new QWindowsVistaTransition; - t->setWidget(w); + QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)); + QWindowsVistaTransition *t = new QWindowsVistaTransition(w); if (!anim) { if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) { //Combo boxes are special cased to avoid cleartype issues @@ -1692,7 +1694,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle t->setDuration(500); } - if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget))) { anim->paint(painter, option); return; } @@ -2338,29 +2340,6 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt /*! \internal */ -bool QWindowsVistaStyle::event(QEvent *e) -{ - Q_D(QWindowsVistaStyle); - switch (e->type()) { - case QEvent::Timer: - { - QTimerEvent *timerEvent = (QTimerEvent *)e; - if (d->animationTimer.timerId() == timerEvent->timerId()) { - d->timerEvent(); - e->accept(); - return true; - } - } - break; - default: - break; - } - return QWindowsXPStyle::event(e); -} - -/*! - \internal - */ QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const { @@ -2549,53 +2528,9 @@ QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate() { - qDeleteAll(animations); cleanupTreeViewTheming(); } -void QWindowsVistaStylePrivate::timerEvent() -{ - for (int i = animations.size() - 1 ; i >= 0 ; --i) { - - if (animations[i]->widget()) - animations[i]->widget()->update(); - - if (!animations[i]->widget() || - !animations[i]->widget()->isVisible() || - animations[i]->widget()->window()->isMinimized() || - !animations[i]->running() || - !QWindowsVistaStylePrivate::useVista()) - { - QWindowsVistaAnimation *a = animations.takeAt(i); - delete a; - } - } - if (animations.size() == 0 && animationTimer.isActive()) { - animationTimer.stop(); - } -} - -void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w) -{ - for (int i = animations.size() - 1 ; i >= 0 ; --i) { - if (animations[i]->widget() == w) { - QWindowsVistaAnimation *a = animations.takeAt(i); - delete a; - break; - } - } -} - -void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t) -{ - Q_Q(QWindowsVistaStyle); - stopAnimation(t->widget()); - animations.append(t); - if (animations.size() > 0 && !animationTimer.isActive()) { - animationTimer.start(45, q); - } -} - bool QWindowsVistaStylePrivate::transitionsEnabled() const { BOOL animEnabled = false; @@ -2607,19 +2542,6 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const return false; } - -QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const -{ - if (!widget) - return 0; - foreach (QWindowsVistaAnimation *a, animations) { - if (a->widget() == widget) - return a; - } - return 0; -} - - /*! \internal Returns true if all the necessary theme engine symbols were resolved. diff --git a/src/widgets/styles/qwindowsvistastyle.h b/src/widgets/styles/qwindowsvistastyle.h index 5a030afddc..0b17881101 100644 --- a/src/widgets/styles/qwindowsvistastyle.h +++ b/src/widgets/styles/qwindowsvistastyle.h @@ -88,7 +88,6 @@ public: void polish(QPalette &pal); void polish(QApplication *app); void unpolish(QApplication *app); - bool event(QEvent *event); QPalette standardPalette() const; private: diff --git a/src/widgets/styles/qwindowsvistastyle_p.h b/src/widgets/styles/qwindowsvistastyle_p.h index faf3777025..1d427fe45c 100644 --- a/src/widgets/styles/qwindowsvistastyle_p.h +++ b/src/widgets/styles/qwindowsvistastyle_p.h @@ -57,6 +57,7 @@ #if !defined(QT_NO_STYLE_WINDOWSVISTA) #include <private/qwindowsxpstyle_p.h> +#include <private/qstyleanimation_p.h> #include <private/qpaintengine_raster_p.h> #include <qlibrary.h> #include <qpaintengine.h> @@ -83,7 +84,6 @@ #include <qdialogbuttonbox.h> #include <qinputdialog.h> #include <qtableview.h> -#include <qbasictimer.h> #include <qdatetime.h> #include <qcommandlinkbutton.h> @@ -135,57 +135,50 @@ QT_BEGIN_NAMESPACE #define TDLG_SECONDARYPANEL 8 #endif -class QWindowsVistaAnimation +class QWindowsVistaAnimation : public QStyleAnimation { -public : - QWindowsVistaAnimation() : _running(true) { } + Q_OBJECT +public: + QWindowsVistaAnimation(QObject *target) : QStyleAnimation(target), _duration(-1) { } virtual ~QWindowsVistaAnimation() { } - QWidget * widget() const { return _widget; } - bool running() const { return _running; } - const QTime &startTime() const { return _startTime; } - void setRunning(bool val) { _running = val; } - void setWidget(QWidget *widget) { _widget = widget; } - void setStartTime(const QTime &startTime) { _startTime = startTime; } virtual void paint(QPainter *painter, const QStyleOption *option); + virtual bool isUpdateNeeded() const; + virtual int duration() const { return _duration; } + //set time in ms to complete a state transition / pulse cycle + void setDuration(int duration) { _duration = duration; } protected: void drawBlendedImage(QPainter *painter, QRect rect, float value); - QTime _startTime; - QPointer<QWidget> _widget; QImage _primaryImage; QImage _secondaryImage; QImage _tempImage; - bool _running; + int _duration; }; // Handles state transition animations class QWindowsVistaTransition : public QWindowsVistaAnimation { -public : - QWindowsVistaTransition() : QWindowsVistaAnimation() {} + Q_OBJECT +public: + QWindowsVistaTransition(QObject *target) : QWindowsVistaAnimation(target) {} virtual ~QWindowsVistaTransition() { } - void setDuration(int duration) { _duration = duration; } void setStartImage(const QImage &image) { _primaryImage = image; } void setEndImage(const QImage &image) { _secondaryImage = image; } virtual void paint(QPainter *painter, const QStyleOption *option); - int duration() const { return _duration; } - int _duration; //set time in ms to complete a state transition }; // Handles pulse animations (default buttons) class QWindowsVistaPulse: public QWindowsVistaAnimation { -public : - QWindowsVistaPulse() : QWindowsVistaAnimation() {} + Q_OBJECT +public: + QWindowsVistaPulse(QObject *target) : QWindowsVistaAnimation(target) {} virtual ~QWindowsVistaPulse() { } - void setDuration(int duration) { _duration = duration; } void setPrimaryImage(const QImage &image) { _primaryImage = image; } void setAlternateImage(const QImage &image) { _secondaryImage = image; } virtual void paint(QPainter *painter, const QStyleOption *option); - int duration() const { return _duration; } - int _duration; //time in ms to complete a pulse cycle }; @@ -198,18 +191,12 @@ public: ~QWindowsVistaStylePrivate(); static bool resolveSymbols(); static inline bool useVista(); - void startAnimation(QWindowsVistaAnimation *); - void stopAnimation(const QWidget *); - QWindowsVistaAnimation* widgetAnimation(const QWidget *) const; - void timerEvent(); bool transitionsEnabled() const; private: bool initTreeViewTheming(); void cleanupTreeViewTheming(); - QList <QWindowsVistaAnimation*> animations; - QBasicTimer animationTimer; HWND m_treeViewHelper; }; diff --git a/src/widgets/styles/styles.pri b/src/widgets/styles/styles.pri index 6ba9875236..1aae0d89f3 100644 --- a/src/widgets/styles/styles.pri +++ b/src/widgets/styles/styles.pri @@ -3,6 +3,7 @@ HEADERS += \ styles/qdrawutil.h \ styles/qstyle.h \ + styles/qstyleanimation_p.h \ styles/qstylefactory.h \ styles/qstyleoption.h \ styles/qstyleplugin.h \ @@ -11,12 +12,14 @@ HEADERS += \ styles/qstylehelper_p.h \ styles/qproxystyle.h \ styles/qproxystyle_p.h \ + styles/qcommonstyle_p.h \ styles/qstylepainter.h \ styles/qstylesheetstyle_p.h SOURCES += \ styles/qdrawutil.cpp \ styles/qstyle.cpp \ + styles/qstyleanimation.cpp \ styles/qstylefactory.cpp \ styles/qstyleoption.cpp \ styles/qstyleplugin.cpp \ @@ -126,6 +129,18 @@ contains( styles, cleanlooks ) { DEFINES += QT_NO_STYLE_CLEANLOOKS } +contains( styles, fusion ) { + HEADERS += styles/qfusionstyle.h + HEADERS += styles/qfusionstyle_p.h + SOURCES += styles/qfusionstyle.cpp + !contains( styles, windows ) { + styles += windows + DEFINES+= QT_STYLE_WINDOWS + } +} else { + DEFINES += QT_NO_STYLE_FUSION +} + contains( styles, windows ) { HEADERS += styles/qwindowsstyle.h SOURCES += styles/qwindowsstyle.cpp diff --git a/src/widgets/widgets/qcheckbox.cpp b/src/widgets/widgets/qcheckbox.cpp index c496198368..29ac80c77d 100644 --- a/src/widgets/widgets/qcheckbox.cpp +++ b/src/widgets/widgets/qcheckbox.cpp @@ -377,7 +377,7 @@ bool QCheckBox::event(QEvent *e) { Q_D(QCheckBox); if (e->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || e->type() == QEvent::MacSizeChange #endif ) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 870e25b241..16de0da4ac 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1597,7 +1597,10 @@ void QComboBox::setIconSize(const QSize &size) \property QComboBox::editable \brief whether the combo box can be edited by the user - By default, this property is false. + By default, this property is false. The effect of editing depends + on the insert policy. + + \sa InsertPolicy */ bool QComboBox::isEditable() const { @@ -2657,7 +2660,7 @@ void QComboBox::changeEvent(QEvent *e) switch (e->type()) { case QEvent::StyleChange: d->updateDelegate(); -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC case QEvent::MacSizeChange: #endif d->sizeHint = QSize(); // invalidate size hint diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index 1a2ef8f645..7868690e49 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -1036,7 +1036,7 @@ bool QDateTimeEdit::event(QEvent *event) d->updateEdit(); break; case QEvent::StyleChange: -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC case QEvent::MacSizeChange: #endif d->setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem); diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp index c278b4f0ac..d25332a077 100644 --- a/src/widgets/widgets/qdialogbuttonbox.cpp +++ b/src/widgets/widgets/qdialogbuttonbox.cpp @@ -1204,7 +1204,7 @@ void QDialogButtonBox::changeEvent(QEvent *event) it.key()->setStyle(newStyle); } // fallthrough intended -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC case QEvent::MacSizeChange: #endif d->resetLayout(); diff --git a/src/widgets/widgets/qframe.cpp b/src/widgets/widgets/qframe.cpp index 6d3ce9be92..3697a2a01f 100644 --- a/src/widgets/widgets/qframe.cpp +++ b/src/widgets/widgets/qframe.cpp @@ -518,7 +518,7 @@ void QFrame::changeEvent(QEvent *ev) { Q_D(QFrame); if (ev->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || ev->type() == QEvent::MacSizeChange #endif ) diff --git a/src/widgets/widgets/qgroupbox.cpp b/src/widgets/widgets/qgroupbox.cpp index 7705edd941..19a0368d94 100644 --- a/src/widgets/widgets/qgroupbox.cpp +++ b/src/widgets/widgets/qgroupbox.cpp @@ -688,7 +688,7 @@ void QGroupBox::changeEvent(QEvent *ev) d->_q_setChildrenEnabled(false); } } else if (ev->type() == QEvent::FontChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || ev->type() == QEvent::MacSizeChange #endif || ev->type() == QEvent::StyleChange) { diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index 8c5026d5f6..d4ba3b2265 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -974,7 +974,7 @@ bool QLabel::event(QEvent *e) if (d->control) d->textLayoutDirty = true; } else if (e->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || e->type() == QEvent::MacSizeChange #endif ) { diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp index 8f0da78613..b7726e7771 100644 --- a/src/widgets/widgets/qprogressbar.cpp +++ b/src/widgets/widgets/qprogressbar.cpp @@ -562,7 +562,7 @@ bool QProgressBar::event(QEvent *e) { Q_D(QProgressBar); if (e->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || e->type() == QEvent::MacSizeChange #endif ) diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index 16e06872ae..5e8d7d16bd 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -674,7 +674,7 @@ bool QPushButton::event(QEvent *e) dialog->d_func()->setMainDefault(this); } } else if (e->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || e->type() == QEvent::MacSizeChange #endif ) { diff --git a/src/widgets/widgets/qradiobutton.cpp b/src/widgets/widgets/qradiobutton.cpp index d257121d20..78d53ad0e6 100644 --- a/src/widgets/widgets/qradiobutton.cpp +++ b/src/widgets/widgets/qradiobutton.cpp @@ -257,7 +257,7 @@ bool QRadioButton::event(QEvent *e) { Q_D(QRadioButton); if (e->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || e->type() == QEvent::MacSizeChange #endif ) diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index fc11232f18..6a11c6d88c 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -1258,7 +1258,7 @@ bool QSpinBox::event(QEvent *event) { Q_D(QSpinBox); if (event->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || event->type() == QEvent::MacSizeChange #endif ) diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 903f496ab7..f9325e6352 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -185,6 +185,7 @@ void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const #ifndef QT_NO_TABWIDGET if (const QTabWidget *tw = qobject_cast<const QTabWidget *>(parentWidget())) { + option->features |= QStyleOptionTab::HasFrame; if (tw->cornerWidget(Qt::TopLeftCorner) || tw->cornerWidget(Qt::BottomLeftCorner)) option->cornerWidgets |= QStyleOptionTab::LeftCornerWidget; if (tw->cornerWidget(Qt::TopRightCorner) || tw->cornerWidget(Qt::BottomRightCorner)) diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp index 717550b2ec..963b86adc1 100644 --- a/src/widgets/widgets/qtabwidget.cpp +++ b/src/widgets/widgets/qtabwidget.cpp @@ -1050,7 +1050,7 @@ bool QTabWidget::event(QEvent *ev) void QTabWidget::changeEvent(QEvent *ev) { if (ev->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || ev->type() == QEvent::MacSizeChange #endif ) diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index 955f59ec47..d49bc98e47 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -573,7 +573,7 @@ void QToolButton::changeEvent(QEvent *e) if (qobject_cast<QToolBar*>(parentWidget())) d->autoRaise = true; } else if (e->type() == QEvent::StyleChange -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC || e->type() == QEvent::MacSizeChange #endif ) { |