diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-03-30 08:28:42 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-03-30 08:28:42 (GMT) |
commit | 571454cef27b8e377806ce25f457db0902e4b262 (patch) | |
tree | 9688ea234b375549a60a4addabd90ede5e7ddc3a /src | |
parent | b3a2c210973a77d1517d017637a3d6ef849f4089 (diff) | |
parent | 9748269cb58266fdfdac2c8820dad8c473dcf512 (diff) | |
download | Qt-571454cef27b8e377806ce25f457db0902e4b262.zip Qt-571454cef27b8e377806ce25f457db0902e4b262.tar.gz Qt-571454cef27b8e377806ce25f457db0902e4b262.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into windows-7-multitouch
Diffstat (limited to 'src')
57 files changed, 1144 insertions, 424 deletions
diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index af48a6e..96840d0 100644 --- a/src/3rdparty/webkit/VERSION +++ b/src/3rdparty/webkit/VERSION @@ -8,4 +8,4 @@ The commit imported was from the and has the sha1 checksum - 70604503a0365edaeff82ffad7b71f90641fa592 + 1beae2b64b5b1e9b97e82dc94de18ebac1c19efc diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index 10a3840..e8850f3 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,46 @@ +2009-03-27 Zack Rusin <zack@kde.org> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=24280 + + Fix propagation of fill rules when rendering paths in the Qt build. + + * platform/graphics/qt/GraphicsContextQt.cpp: + (WebCore::toQtFillRule): + (WebCore::GraphicsContext::fillPath): + (WebCore::GraphicsContext::strokePath): + +2009-03-27 Zack Rusin <zack@kde.org> + + Reviewed by Tor Arne Vestbø. + + https://bugs.webkit.org/show_bug.cgi?id=24275 + + Fix text field theming in the Qt build with the KDE 4 Oxygen + style by adjusting the size vertically and horizontally to + set padding on the element equal to the width of the style painted border. + + * platform/qt/RenderThemeQt.cpp: + (WebCore::RenderThemeQt::RenderThemeQt): + (WebCore::RenderThemeQt::computeSizeBasedOnStyle): + (WebCore::RenderThemeQt::adjustTextFieldStyle): + (WebCore::RenderThemeQt::paintTextField): + * platform/qt/RenderThemeQt.h: + +2009-02-06 Dirk Schulze <krit@webkit.org> + + Reviewed by Simon Hausmann. + + Fix bug in clearRect(). Use fillRect() instead of eraseRect() to get + the context transparent. + + [QT] clearRect fill's a given rect with white + https://bugs.webkit.org/show_bug.cgi?id=23728 + + * platform/graphics/qt/GraphicsContextQt.cpp: + (WebCore::GraphicsContext::clearRect): + 2009-03-19 Simon Hausmann <simon.hausmann@nokia.com> Reviewed by Tor Arne Vestbø. diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 80a6390..936c1ea 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -168,6 +168,18 @@ static inline QGradient applySpreadMethod(QGradient gradient, GradientSpreadMeth return gradient; } +static inline Qt::FillRule toQtFillRule(WindRule rule) +{ + switch(rule) { + case RULE_EVENODD: + return Qt::OddEvenFill; + case RULE_NONZERO: + return Qt::WindingFill; + } + qDebug("Qt: unrecognized wind rule!"); + return Qt::OddEvenFill; +} + struct TransparencyLayer { TransparencyLayer(const QPainter* p, const QRect &rect) @@ -541,6 +553,7 @@ void GraphicsContext::fillPath() QPainter *p = m_data->p(); QPainterPath path = m_data->currentPath; + path.setFillRule(toQtFillRule(fillRule())); switch (m_common->state.fillColorSpace) { case SolidColorSpace: @@ -569,6 +582,7 @@ void GraphicsContext::strokePath() QPainter *p = m_data->p(); QPen pen = p->pen(); QPainterPath path = m_data->currentPath; + path.setFillRule(toQtFillRule(fillRule())); switch (m_common->state.strokeColorSpace) { case SolidColorSpace: @@ -815,7 +829,7 @@ void GraphicsContext::clearRect(const FloatRect& rect) QPainter::CompositionMode currentCompositionMode = p->compositionMode(); if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff)) p->setCompositionMode(QPainter::CompositionMode_Source); - p->eraseRect(rect); + p->fillRect(rect, Qt::transparent); if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff)) p->setCompositionMode(currentCompositionMode); } diff --git a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp index cc9d314..a9da76b 100644 --- a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp +++ b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp @@ -41,6 +41,7 @@ #include <QWidget> #include <QPainter> #include <QPushButton> +#include <QLineEdit> #include <QStyleFactory> #include <QStyleOptionButton> #include <QStyleOptionFrameV2> @@ -123,6 +124,12 @@ RenderThemeQt::RenderThemeQt() #endif m_fallbackStyle = 0; + + // this will need to be regenerated when the style changes + QLineEdit lineEdit; + QStyleOptionFrameV2 opt; + m_frameLineWidth = QApplication::style()->pixelMetric(QStyle::PM_DefaultFrameWidth, + &opt, &lineEdit); } RenderThemeQt::~RenderThemeQt() @@ -268,7 +275,7 @@ int RenderThemeQt::minimumMenuListSize(RenderStyle*) const return 7 * fm.width(QLatin1Char('x')); } -static void computeSizeBasedOnStyle(RenderStyle* renderStyle) +void RenderThemeQt::computeSizeBasedOnStyle(RenderStyle* renderStyle) const { // If the width and height are both specified, then we have nothing to do. if (!renderStyle->width().isIntrinsicOrAuto() && !renderStyle->height().isAuto()) @@ -335,13 +342,15 @@ static void computeSizeBasedOnStyle(RenderStyle* renderStyle) int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin; int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin; QStyleOptionFrameV2 opt; - opt.lineWidth = applicationStyle->pixelMetric(QStyle::PM_DefaultFrameWidth, - &opt, 0); + opt.lineWidth = m_frameLineWidth; QSize sz = applicationStyle->sizeFromContents(QStyle::CT_LineEdit, - &opt, - QSize(w, h).expandedTo(QApplication::globalStrut()), - 0); + &opt, + QSize(w, h).expandedTo(QApplication::globalStrut()), + 0); size.setHeight(sz.height()); + + renderStyle->setPaddingLeft(Length(opt.lineWidth, Fixed)); + renderStyle->setPaddingRight(Length(opt.lineWidth, Fixed)); break; } default: @@ -482,6 +491,9 @@ void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, { style->setBackgroundColor(Color::transparent); style->setColor(QApplication::palette().text().color()); + style->resetBorder(); + style->resetPadding(); + computeSizeBasedOnStyle(style); } bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) @@ -495,7 +507,7 @@ bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInf panel.initFrom(p.widget); panel.rect = r; - panel.lineWidth = p.style->pixelMetric(QStyle::PM_DefaultFrameWidth, &panel, p.widget); + panel.lineWidth = m_frameLineWidth; panel.state |= QStyle::State_Sunken; panel.features = QStyleOptionFrameV2::None; diff --git a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h index b4a5064..5c78a72 100644 --- a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h +++ b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h @@ -128,6 +128,7 @@ private: void paintMediaBackground(QPainter* painter, const IntRect& r) const; QColor getMediaControlForegroundColor(RenderObject* o = 0) const; #endif + void computeSizeBasedOnStyle(RenderStyle* renderStyle) const; private: bool supportsFocus(ControlPart) const; @@ -144,6 +145,8 @@ private: QStyle* m_fallbackStyle; QStyle* fallbackStyle(); + + int m_frameLineWidth; }; class StylePainter diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp index 5e3c656..636b6e8 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp @@ -533,6 +533,8 @@ void QWebPagePrivate::updateEditorActions() updateAction(QWebPage::ToggleBold); updateAction(QWebPage::ToggleItalic); updateAction(QWebPage::ToggleUnderline); + updateAction(QWebPage::InsertParagraphSeparator); + updateAction(QWebPage::InsertLineSeparator); } void QWebPagePrivate::timerEvent(QTimerEvent *ev) @@ -1792,6 +1794,13 @@ QAction *QWebPage::action(WebAction action) const text = contextMenuItemTagInspectElement(); break; + case InsertParagraphSeparator: + text = tr("Insert a new paragraph"); + break; + case InsertLineSeparator: + text = tr("Insert a new line"); + break; + case NoWebAction: return 0; } @@ -2319,7 +2328,8 @@ QWebPluginFactory *QWebPage::pluginFactory() const \list \o %Platform% and %Subplatform% are expanded to the windowing system and the operation system. \o %Security% expands to U if SSL is enabled, otherwise N. SSL is enabled if QSslSocket::supportsSsl() returns true. - \o %Locale% is replaced with QLocale::name(). + \o %Locale% is replaced with QLocale::name(). The locale is determined from the view of the QWebPage. If no view is set on the QWebPage, + then a default constructed QLocale is used instead. \o %WebKitVersion% currently expands to 527+ \o %AppVersion% expands to QCoreApplication::applicationName()/QCoreApplication::applicationVersion() if they're set; otherwise defaulting to Qt and the current Qt version. \endlist diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index 0755133..32d27cd 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,25 @@ +2009-03-26 Simon Hausmann <simon.hausmann@nokia.com> + + Rubber-stamped by Tor Arne Vestbø. + + Fix the documentation of the QLocale usage in userAgentForUrl. + + * Api/qwebpage.cpp: + +2009-03-20 Erik L. Bunce <elbunce@xendom.com> + + Reviewed by Simon Hausmann. + + Fix for InsertParagraphSeparator and InsertLineSeparator so that + QWebPage::action() creates QActions for them. Also make sure they get + updated appropriately. + + * Api/qwebpage.cpp: + (QWebPagePrivate::updateEditorActions): + (QWebPage::action): + * tests/qwebpage/tst_qwebpage.cpp: + (tst_QWebPage::textEditing): + 2009-03-20 Erik L. Bunce <elbunce@xendom.com> Reviewed by Tor Arne Vestbø. diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp index 54d342e..d85e880 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp @@ -956,6 +956,8 @@ void tst_QWebPage::textEditing() QVERIFY(page->action(QWebPage::ToggleBold) != 0); QVERIFY(page->action(QWebPage::ToggleItalic) != 0); QVERIFY(page->action(QWebPage::ToggleUnderline) != 0); + QVERIFY(page->action(QWebPage::InsertParagraphSeparator) != 0); + QVERIFY(page->action(QWebPage::InsertLineSeparator) != 0); // right now they are disabled because contentEditable is false QCOMPARE(page->action(QWebPage::DeleteStartOfWord)->isEnabled(), false); @@ -966,6 +968,8 @@ void tst_QWebPage::textEditing() QCOMPARE(page->action(QWebPage::ToggleBold)->isEnabled(), false); QCOMPARE(page->action(QWebPage::ToggleItalic)->isEnabled(), false); QCOMPARE(page->action(QWebPage::ToggleUnderline)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::InsertParagraphSeparator)->isEnabled(), false); + QCOMPARE(page->action(QWebPage::InsertLineSeparator)->isEnabled(), false); // make it editable before navigating the cursor page->setContentEditable(true); @@ -979,6 +983,8 @@ void tst_QWebPage::textEditing() QCOMPARE(page->action(QWebPage::ToggleBold)->isEnabled(), true); QCOMPARE(page->action(QWebPage::ToggleItalic)->isEnabled(), true); QCOMPARE(page->action(QWebPage::ToggleUnderline)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::InsertParagraphSeparator)->isEnabled(), true); + QCOMPARE(page->action(QWebPage::InsertLineSeparator)->isEnabled(), true); delete page; } diff --git a/src/corelib/concurrent/qtconcurrentreducekernel.h b/src/corelib/concurrent/qtconcurrentreducekernel.h index e863b63..2dad519 100644 --- a/src/corelib/concurrent/qtconcurrentreducekernel.h +++ b/src/corelib/concurrent/qtconcurrentreducekernel.h @@ -51,6 +51,7 @@ #include <QtCore/qmap.h> #include <QtCore/qmutex.h> #include <QtCore/qthread.h> +#include <QtCore/qthreadpool.h> #include <QtCore/qvector.h> QT_BEGIN_HEADER @@ -107,7 +108,7 @@ class ReduceKernel const ReduceOptions reduceOptions; QMutex mutex; - int progress, resultsMapSize; + int progress, resultsMapSize, threadCount; ResultsMap resultsMap; bool canReduce(int begin) const @@ -140,7 +141,8 @@ class ReduceKernel public: ReduceKernel(ReduceOptions _reduceOptions) - : reduceOptions(_reduceOptions), progress(0), resultsMapSize(0) + : reduceOptions(_reduceOptions), progress(0), resultsMapSize(0), + threadCount(QThreadPool::globalInstance()->maxThreadCount()) { } void runReduce(ReduceFunctor &reduce, @@ -210,12 +212,12 @@ public: inline bool shouldThrottle() { - return (resultsMapSize > (ReduceQueueThrottleLimit * QThread::idealThreadCount())); + return (resultsMapSize > (ReduceQueueThrottleLimit * threadCount)); } inline bool shouldStartThread() { - return (resultsMapSize <= (ReduceQueueStartLimit * QThread::idealThreadCount())); + return (resultsMapSize <= (ReduceQueueStartLimit * threadCount)); } }; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 05015c0..0e632db 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2179,13 +2179,29 @@ void QObject::deleteLater() Signals and slots *****************************************************************************/ +// list taken from http://en.wikipedia.org/wiki/Thread-Specific_Storage +#if defined(Q_OS_WIN) +// Some people like to dynamically load Qt (LoadLibrary), so we can't use this +#elif defined(Q_CC_GNU) && !defined(Q_WS_QWS) +// GCC has warnings about this not being ported to all archs +// So we only enable what we know to work. More archs can be added later, like Mac +# if defined(Q_OS_LINUX) && (defined(QT_ARCH_I386) || defined(QT_ARCH_X86_64) || defined(QT_ARCH_IA64)) +# define THRSPECIFIC __thread __attribute__((tls_model("local-dynamic"))) +# endif +#elif defined(Q_CC_SUN) || defined(Q_CC_INTEL) || defined(Q_CC_XLC) +# define THRSPECIFIC __thread +#endif + +#ifndef THRSPECIFIC +# define THRSPECIFIC +#endif const int flagged_locations_count = 2; -static const char* flagged_locations[flagged_locations_count] = {0}; +static THRSPECIFIC const char* flagged_locations[flagged_locations_count] = {0}; const char *qFlagLocation(const char *method) { - static int idx = 0; + static THRSPECIFIC int idx = 0; flagged_locations[idx] = method; idx = (idx+1) % flagged_locations_count; return method; diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index cdddf36..77d6599 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -95,8 +95,7 @@ static bool match(const uchar* found, const char* target, uint len) // (normalize it to be without the zero-terminating symbol) if (len > 0 && found[len-1] == '\0') --len; - // 0 means anything, "" means empty - return !found || (qstrncmp((const char *)found, target, len) == 0 && target[len] == '\0'); + return (memcmp(found, target, len) == 0 && target[len] == '\0'); } static uint elfHash(const char *name) @@ -765,8 +764,6 @@ void QTranslatorPrivate::clear() } /*! - \since 4.5 - Returns the translation for the key (\a context, \a sourceText, \a disambiguation). If none is found, also tries (\a context, \a sourceText, ""). If that still fails, returns an empty string. diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp index 71ecab5..96a9940 100644 --- a/src/corelib/thread/qmutexpool.cpp +++ b/src/corelib/thread/qmutexpool.cpp @@ -96,9 +96,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (true)) QMutexPool is destructed. */ QMutexPool::QMutexPool(bool recursive, int size) - : count(size), recurs(recursive) + : mutexes(size), count(size), recurs(recursive) { - mutexes = new QMutex*[count]; for (int index = 0; index < count; ++index) { mutexes[index] = 0; } @@ -110,13 +109,10 @@ QMutexPool::QMutexPool(bool recursive, int size) */ QMutexPool::~QMutexPool() { - QMutexLocker locker(&mutex); for (int index = 0; index < count; ++index) { delete mutexes[index]; mutexes[index] = 0; } - delete [] mutexes; - mutexes = 0; } /*! @@ -138,12 +134,9 @@ QMutex *QMutexPool::get(const void *address) if (!mutexes[index]) { // mutex not created, create one - - QMutexLocker locker(&mutex); - // we need to check once again that the mutex hasn't been created, since - // 2 threads could be trying to create a mutex at the same index... - if (!mutexes[index]) - mutexes[index] = new QMutex(recurs ? QMutex::Recursive : QMutex::NonRecursive); + QMutex *newMutex = new QMutex(recurs ? QMutex::Recursive : QMutex::NonRecursive); + if (!mutexes[index].testAndSetOrdered(0, newMutex)) + delete newMutex; } return mutexes[index]; diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h index 65a3b54..1009ebb 100644 --- a/src/corelib/thread/qmutexpool_p.h +++ b/src/corelib/thread/qmutexpool_p.h @@ -53,7 +53,9 @@ // We mean it. // +#include "QtCore/qatomic.h" #include "QtCore/qmutex.h" +#include "QtCore/qvarlengtharray.h" #ifndef QT_NO_THREAD @@ -70,8 +72,7 @@ public: static QMutex *globalInstanceGet(const void *address); private: - QMutex mutex; - QMutex **mutexes; + QVarLengthArray<QAtomicPointer<QMutex>, 128> mutexes; int count; bool recurs; }; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 91b9cb1..8c701f5 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -137,6 +137,7 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) if (!q_dbus_timeout_get_enabled(timeout)) return true; + QDBusWatchAndTimeoutLocker locker(AddTimeoutAction, d); if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) { // correct thread return qDBusRealAddTimeout(d, timeout, q_dbus_timeout_get_interval(timeout)); @@ -152,7 +153,6 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms) { - QDBusWatchAndTimeoutLocker locker(AddTimeoutAction, d); Q_ASSERT(d->timeouts.keys(timeout).isEmpty()); int timerId = d->startTimer(ms); @@ -921,10 +921,9 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *p) rootNode(QString(QLatin1Char('/'))) { static const bool threads = qDBusInitThreads(); - static const int debugging = qgetenv("QDBUS_DEBUG").toInt(); + static const int debugging = ::isDebugging = qgetenv("QDBUS_DEBUG").toInt(); Q_UNUSED(threads) - ::isDebugging = debugging; #ifdef QDBUS_THREAD_DEBUG if (debugging > 1) qdbusThreadDebug = qdbusDefaultThreadDebug; @@ -1036,15 +1035,16 @@ void QDBusConnectionPrivate::customEvent(QEvent *e) QDBusLockerBase::BeforeDeliver, this); switch (ev->subtype) { - case QDBusConnectionCallbackEvent::AddTimeout: + case QDBusConnectionCallbackEvent::AddTimeout: { + QDBusWatchAndTimeoutLocker locker(RealAddTimeoutAction, this); while (!timeoutsPendingAdd.isEmpty()) { QPair<DBusTimeout *, int> entry = timeoutsPendingAdd.takeFirst(); qDBusRealAddTimeout(this, entry.first, entry.second); } break; + } case QDBusConnectionCallbackEvent::KillTimer: - qDebug() << QThread::currentThread() << "RemoveTimeout: killing timer" << (ev->timerId & 0xffffff); killTimer(ev->timerId); break; diff --git a/src/dbus/qdbuspendingreply.h b/src/dbus/qdbuspendingreply.h index 3880a7f..5ec9800 100644 --- a/src/dbus/qdbuspendingreply.h +++ b/src/dbus/qdbuspendingreply.h @@ -95,7 +95,7 @@ namespace QDBusPendingReplyTypes { enum { Total = Next::Total + 1 }; static inline void fillMetaTypes(int *p) { - *p = metaTypeFor<T1>(); + *p = metaTypeFor<T1>(0); Next::fillMetaTypes(++p); } }; @@ -171,7 +171,7 @@ public: Q_ASSERT_X(Index < count() && Index >= 0, "QDBusPendingReply::argumentAt", "Index out of bounds"); typedef typename Select<Index>::Type ResultType; - return qdbus_cast<ResultType>(argumentAt(Index)); + return qdbus_cast<ResultType>(argumentAt(Index), 0); } inline typename Select<0>::Type value() const diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h index 715bd6f..20d819f 100644 --- a/src/dbus/qdbusthreaddebug_p.h +++ b/src/dbus/qdbusthreaddebug_p.h @@ -92,9 +92,10 @@ enum ThreadAction { PendingCallBlockAction = 28, AddTimeoutAction = 50, - RemoveTimeoutAction = 51, - KillTimerAction = 52, - TimerEventAction = 53, + RealAddTimeoutAction = 51, + RemoveTimeoutAction = 52, + KillTimerAction = 58, + TimerEventAction = 59, AddWatchAction = 60, RemoveWatchAction = 61, ToggleWatchAction = 62, diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 0b51c8c..7d0d503 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -8229,6 +8229,8 @@ void QGraphicsTextItem::setTabChangesFocus(bool b) Returns true if the \gui Tab key will cause the widget to change focus; otherwise, false is returned. + By default, this behavior is disabled, and this function will return false. + \sa setTabChangesFocus() */ bool QGraphicsTextItem::tabChangesFocus() const diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 1aa6558..586227a 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -1,6 +1,7 @@ TARGET = QtGui QPRO_PWD = $$PWD QT = core +CONFIG += force_uic DEFINES += QT_BUILD_GUI_LIB QT_NO_USING_NAMESPACE win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000 diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp index b0075b2..973cd78 100644 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -303,7 +303,7 @@ void QMacPixmapData::fromImage(const QImage &img, else one_bit = one_bit >> (x % 8); if ((one_bit & 0x01)) - *(drow+x) = 0x00000000; + *(drow+x) = 0xFF000000; else *(drow+x) = 0xFFFFFFFF; } diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 1df442f..6babda9 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -3351,15 +3351,24 @@ int QApplication::x11ProcessEvent(XEvent* event) // update the size for desktop widget int scr = X11->ptrXRRRootToScreen(X11->display, event->xany.window); - QWidget *w = desktop()->screen(scr); + QDesktopWidget *desktop = QApplication::desktop(); + QWidget *w = desktop->screen(scr); QSize oldSize(w->size()); w->data->crect.setWidth(DisplayWidth(X11->display, scr)); w->data->crect.setHeight(DisplayHeight(X11->display, scr)); - if (w->size() != oldSize) { - QResizeEvent e(w->size(), oldSize); - QApplication::sendEvent(w, &e); - emit desktop()->resized(scr); - } + QVarLengthArray<QRect> oldSizes(desktop->numScreens()); + for (int i = 0; i < desktop->numScreens(); ++i) + oldSizes[i] = desktop->screenGeometry(i); + QResizeEvent e(w->size(), oldSize); + QApplication::sendEvent(w, &e); + for (int i = 0; i < qMin(oldSizes.count(), desktop->numScreens()); ++i) { + if (oldSizes[i] != desktop->screenGeometry(i)) + emit desktop->resized(i); + } + for (int i = oldSizes.count(); i < desktop->numScreens(); ++i) + emit desktop->resized(i); // added + for (int i = desktop->numScreens(); i < oldSizes.count(); ++i) + emit desktop->resized(i); // removed } #endif // QT_NO_XRANDR diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index 6aeee34..c17b30c 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -43,10 +43,14 @@ #ifdef QT_MAC_USE_COCOA #import <private/qt_cocoa_helpers_mac_p.h> #import <private/qcocoawindow_mac_p.h> +#import <private/qcocoawindowdelegate_mac_p.h> +#import <private/qcocoaview_mac_p.h> #import <private/qcocoawindowcustomthemeframe_mac_p.h> #include <QtGui/QWidget> +extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm + QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(QCocoaPanel) @@ -60,14 +64,110 @@ QT_USE_NAMESPACE return !(isPopup || isToolTip); } +/*********************************************************************** + BEGIN Copy and Paste between QCocoaWindow and QCocoaPanel + This is a bit unfortunate, but thanks to the dynamic dispatch we + have to duplicate this code or resort to really silly forwarding methods +**************************************************************************/ + +/* + The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever + get hit. We automatically say we can be first responder if we are a window. + So, the handling should get handled by the view. This is here more as a + last resort (i.e., this is code that can potentially be removed). + */ + +- (void)keyDown:(NSEvent *)theEvent +{ + bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); + if (!keyOK) + [super keyDown:theEvent]; +} + +- (void)keyUp:(NSEvent *)theEvent +{ + bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); + if (!keyOK) + [super keyUp:theEvent]; +} + +- (void)flagsChanged:(NSEvent *)theEvent +{ + qt_dispatchModifiersChanged(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); + [super flagsChanged:theEvent]; +} + + +- (void)tabletProximity:(NSEvent *)tabletEvent +{ + qt_dispatchTabletProximityEvent(tabletEvent); +} + - (void)sendEvent:(NSEvent *)event { [self retain]; - [super sendEvent:event]; + + QWidget *widget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; + QCocoaView *view = static_cast<QCocoaView *>(qt_mac_nativeview_for(widget)); + Qt::MouseButton mouseButton = cocoaButton2QtButton([event buttonNumber]); + + // sometimes need to redirect mouse events to the popup. + QWidget *popup = qAppInstance()->activePopupWidget(); + if (popup && popup != widget) { + switch([event type]) + { + case NSLeftMouseDown: + qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton); + // Don't call super here. This prevents us from getting the mouseUp event, + // which we need to send even if the mouseDown event was not accepted. + // (this is standard Qt behavior.) + break; + case NSRightMouseDown: + case NSOtherMouseDown: + if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonPress, mouseButton)) + [super sendEvent:event]; + break; + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseButtonRelease, mouseButton)) + [super sendEvent:event]; + break; + case NSMouseMoved: + qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, Qt::NoButton); + break; + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = view; + [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = event; + if (!qt_mac_handleMouseEvent(view, event, QEvent::MouseMove, mouseButton)) + [super sendEvent:event]; + break; + default: + [super sendEvent:event]; + break; + } + } else { + [super sendEvent:event]; + } qt_mac_dispatchNCMouseMessage(self, event, [self QT_MANGLE_NAMESPACE(qt_qwidget)], leftButtonIsRightButton); + + [self release]; } + +- (BOOL)makeFirstResponder:(NSResponder *)responder +{ + if (responder == nil) + return NO; + return [super makeFirstResponder:responder]; +} + +/*********************************************************************** + END Copy and Paste between QCocoaWindow and QCocoaPanel +***********************************************************************/ + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask { if (styleMask & QtMacCustomizeWindow) diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index 6b30444..ba121cd 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -86,6 +86,12 @@ extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview. return YES; } +/*********************************************************************** + BEGIN Copy and Paste between QCocoaWindow and QCocoaPanel + This is a bit unfortunate, but thanks to the dynamic dispatch we + have to duplicate this code or resort to really silly forwarding methods +**************************************************************************/ + /* The methods keyDown, keyUp, and flagsChanged... These really shouldn't ever get hit. We automatically say we can be first responder if we are a window. @@ -173,6 +179,18 @@ extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview. [self release]; } + +- (BOOL)makeFirstResponder:(NSResponder *)responder +{ + if (responder == nil) + return NO; + return [super makeFirstResponder:responder]; +} + +/*********************************************************************** + END Copy and Paste between QCocoaWindow and QCocoaPanel +***********************************************************************/ + + (Class)frameViewClassForStyleMask:(NSUInteger)styleMask { if (styleMask & QtMacCustomizeWindow) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 06810e0..09162ee 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -164,6 +164,7 @@ static inline bool bypassGraphicsProxyWidget(QWidget *p) #endif extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp +extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp QWidgetPrivate::QWidgetPrivate(int version) : QObjectPrivate(version), extra(0), focus_child(0) @@ -1400,7 +1401,13 @@ int QWidgetPrivate::maxInstances = 0; // Maximum number of widget instances void QWidgetPrivate::setWinId(WId id) // set widget identifier { Q_Q(QWidget); - if (mapper && data.winid) { + // the user might create a widget with Qt::Desktop window + // attribute (or create another QDesktopWidget instance), which + // will have the same windowid (the root window id) as the + // qt_desktopWidget. We should not add the second desktop widget + // to the mapper. + bool userDesktopWidget = qt_desktopWidget != 0 && qt_desktopWidget != q && q->windowType() == Qt::Desktop; + if (mapper && data.winid && !userDesktopWidget) { mapper->remove(data.winid); uncreatedWidgets->insert(q); } @@ -1409,7 +1416,7 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier #if defined(Q_WS_X11) hd = id; // X11: hd == ident #endif - if (mapper && id) { + if (mapper && id && !userDesktopWidget) { mapper->insert(data.winid, q); uncreatedWidgets->remove(q); } @@ -9786,12 +9793,21 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) } break; #endif - case Qt::WA_NativeWindow: + case Qt::WA_NativeWindow: { + QInputContext *ic = 0; + if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) { + ic = d->inputContext(); + ic->reset(); + ic->setFocusWidget(0); + } if (!qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget()) parentWidget()->d_func()->enforceNativeChildren(); if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) d->createWinId(); + if (ic) + ic->setFocusWidget(this); break; + } case Qt::WA_PaintOnScreen: d->updateIsOpaque(); #if defined(Q_WS_WIN) || defined(Q_WS_X11) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index f599b7c..7a586e1 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2514,6 +2514,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } updateIsOpaque(); + if (q->hasFocus()) + setFocus_sys(); if (!topLevel && initializeWindow) setWSGeometry(); diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index e9f1bb3..d931f55 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -62,6 +62,7 @@ #include <private/qpaintengine_x11_p.h> #include <private/qfontengine_x11_p.h> #include <private/qwidget_p.h> +#include <private/qpainterpath_p.h> #include "qpen.h" #include "qcolor.h" @@ -1479,14 +1480,10 @@ void QX11PaintEngine::drawEllipse(const QRect &rect) return; } d->setupAdaptedOrigin(rect.topLeft()); - if (d->has_brush) { // draw filled ellipse - if (!d->has_pen) { - XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64); + if (d->has_brush) { // draw filled ellipse + XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w, h, 0, 360*64); + if (!d->has_pen) // make smoother outline XDrawArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64); - return; - } else{ - XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w, h, 0, 360*64); - } } if (d->has_pen) // draw outline XDrawArc(d->dpy, d->hd, d->gc, x, y, w, h, 0, 360*64); @@ -1760,9 +1757,11 @@ void QX11PaintEngine::drawPath(const QPainterPath &path) QPainterPath stroke; qreal width = d->cpen.widthF(); QPolygonF poly; + QRectF deviceRect(0, 0, d->pdev->width(), d->pdev->height()); // necessary to get aliased alphablended primitives to be drawn correctly if (d->cpen.isCosmetic() || d->has_scaling_xform) { stroker.setWidth(width == 0 ? 1 : width * d->xform_scale); + stroker.d_ptr->stroker.setClipRect(deviceRect); stroke = stroker.createStroke(path * d->matrix); if (stroke.isEmpty()) return; @@ -1770,6 +1769,7 @@ void QX11PaintEngine::drawPath(const QPainterPath &path) d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, false); } else { stroker.setWidth(width); + stroker.d_ptr->stroker.setClipRect(d->matrix.inverted().mapRect(deviceRect)); stroke = stroker.createStroke(path); if (stroke.isEmpty()) return; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 0d985c3..b5e092c 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -2443,21 +2443,13 @@ void qt_path_stroke_cubic_to(qfixed c1x, qfixed c1y, \sa QPen, QBrush */ -class QPainterPathStrokerPrivate +QPainterPathStrokerPrivate::QPainterPathStrokerPrivate() + : dashOffset(0) { -public: - QPainterPathStrokerPrivate() - : dashOffset(0) - { - stroker.setMoveToHook(qt_path_stroke_move_to); - stroker.setLineToHook(qt_path_stroke_line_to); - stroker.setCubicToHook(qt_path_stroke_cubic_to); - } - - QStroker stroker; - QVector<qfixed> dashPattern; - qreal dashOffset; -}; + stroker.setMoveToHook(qt_path_stroke_move_to); + stroker.setLineToHook(qt_path_stroke_line_to); + stroker.setCubicToHook(qt_path_stroke_cubic_to); +} /*! Creates a new stroker. @@ -2501,6 +2493,7 @@ QPainterPath QPainterPathStroker::createStroke(const QPainterPath &path) const QDashStroker dashStroker(&d->stroker); dashStroker.setDashPattern(d->dashPattern); dashStroker.setDashOffset(d->dashOffset); + dashStroker.setClipRect(d->stroker.clipRect()); dashStroker.strokePath(path, &stroke, QTransform()); } stroke.setFillRule(Qt::WindingFill); diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 56d783d..e343a28 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -283,6 +283,8 @@ public: QPainterPath createStroke(const QPainterPath &path) const; private: + friend class QX11PaintEngine; + QPainterPathStrokerPrivate *d_ptr; }; diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index 93f9704..29c48df 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -61,9 +61,20 @@ #include <qdebug.h> #include <private/qvectorpath_p.h> +#include <private/qstroker_p.h> QT_BEGIN_NAMESPACE +class QPainterPathStrokerPrivate +{ +public: + QPainterPathStrokerPrivate(); + + QStroker stroker; + QVector<qfixed> dashPattern; + qreal dashOffset; +}; + class QPolygonF; class QVectorPathConverter; diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index 468ada9..11f4d26 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -44,6 +44,7 @@ #if !defined(QT_NO_STYLE_CLEANLOOKS) || defined(QT_PLUGIN) +#include <private/qstylehelper_p.h> #include "qwindowsstyle_p.h" #include <qcombobox.h> #include <qpushbutton.h> @@ -72,7 +73,7 @@ QT_BEGIN_NAMESPACE -static const bool UsePixmapCache = true; +using namespace QStyleHelper; enum Direction { TopDown, @@ -553,26 +554,6 @@ static void qt_cleanlooks_draw_buttongradient(QPainter *painter, const QRect &re delete gradient; } -static QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size) -{ - QString tmp; - const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option); - tmp.sprintf("%s-%d-%d-%lld-%dx%d-%d", key.toLatin1().constData(), uint(option->state), - complexOption ? uint(complexOption->activeSubControls) : uint(0), - option->palette.cacheKey(), size.width(), size.height(), option->direction); -#ifndef QT_NO_SPINBOX - if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { - tmp.append(QLatin1Char('-')); - tmp.append(QString::number(spinBox->buttonSymbols)); - tmp.append(QLatin1Char('-')); - tmp.append(QString::number(spinBox->stepEnabled)); - tmp.append(QLatin1Char('-')); - tmp.append(QLatin1Char(spinBox->frame ? '1' : '0')); - } -#endif // QT_NO_SPINBOX - return tmp; -} - static void qt_cleanlooks_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken) { QColor dark; @@ -1664,7 +1645,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o // Draws the header in tables. if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { QPixmap cache; - QString pixmapName = uniqueName(QLatin1String("headersection"), option, option->rect.size()); + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size()); pixmapName += QLatin1String("-") + QString::number(int(header->position)); pixmapName += QLatin1String("-") + QString::number(int(header->orientation)); QRect r = option->rect; @@ -2456,7 +2437,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp case CC_SpinBox: if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { QPixmap cache; - QString pixmapName = uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size()); + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size()); if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) { cache = QPixmap(spinBox->rect.size()); cache.fill(Qt::transparent); @@ -3137,7 +3118,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp // The AddLine (down/right) button if (scrollBar->subControls & SC_ScrollBarAddLine) { - QString addLinePixmapName = uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16)); + QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16)); QRect pixmapRect = scrollBarAddLine; if (isEnabled) { QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1); @@ -3198,7 +3179,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp bool isEnabled = (comboBox->state & State_Enabled); bool focus = isEnabled && (comboBox->state & State_HasFocus); QPixmap cache; - QString pixmapName = uniqueName(QLatin1String("combobox"), option, comboBox->rect.size()); + QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size()); if (sunken) pixmapName += QLatin1String("-sunken"); if (comboBox->editable) @@ -3421,7 +3402,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp highlightAlpha.setAlpha(80); if ((option->subControls & SC_SliderGroove) && groove.isValid()) { - QString groovePixmapName = uniqueName(QLatin1String("slider_groove"), option, groove.size()); + QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size()); QRect pixmapRect(0, 0, groove.width(), groove.height()); // draw background groove @@ -3501,7 +3482,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp // draw handle if ((option->subControls & SC_SliderHandle) ) { - QString handlePixmapName = uniqueName(QLatin1String("slider_handle"), option, handle.size()); + QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size()); if (!UsePixmapCache || !QPixmapCache::find(handlePixmapName, cache)) { cache = QPixmap(handle.size()); cache.fill(Qt::transparent); @@ -3656,6 +3637,12 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp } break; #endif // QT_NO_SLIDER +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option)) + QStyleHelper::drawDial(dial, painter); + break; +#endif // QT_NO_DIAL default: QWindowsStyle::drawComplexControl(control, option, painter, widget); break; diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index 3cae08a..86a3ce0 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -66,6 +66,7 @@ #include <private/qapplication_p.h> #include <private/qcommonstylepixmaps_p.h> #include <private/qmath_p.h> +#include <private/qstylehelper_p.h> #include <qdebug.h> #include <qtextformat.h> #include <qwizard.h> @@ -3189,47 +3190,6 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, } #ifndef QT_NO_DIAL -static qreal angle(const QPointF &p1, const QPointF &p2) -{ - static const qreal rad_factor = 180 / Q_PI; - qreal _angle = 0; - - if (p1.x() == p2.x()) { - if (p1.y() < p2.y()) - _angle = 270; - else - _angle = 90; - } else { - qreal x1, x2, y1, y2; - - if (p1.x() <= p2.x()) { - x1 = p1.x(); y1 = p1.y(); - x2 = p2.x(); y2 = p2.y(); - } else { - x2 = p1.x(); y2 = p1.y(); - x1 = p2.x(); y1 = p2.y(); - } - - qreal m = -(y2 - y1) / (x2 - x1); - _angle = atan(m) * rad_factor; - - if (p1.x() < p2.x()) - _angle = 180 - _angle; - else - _angle = -_angle; - } - return _angle; -} - -static int calcBigLineSize(int radius) -{ - int bigLineSize = radius / 6; - if (bigLineSize < 4) - bigLineSize = 4; - if (bigLineSize > radius / 2) - bigLineSize = radius / 2; - return bigLineSize; -} static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) { @@ -3250,7 +3210,7 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) int xc = width / 2; int yc = height / 2; - int len = r - calcBigLineSize(r) - 5; + int len = r - QStyleHelper::calcBigLineSize(r) - 5; if (len < 5) len = 5; int back = len / 2; @@ -3265,45 +3225,6 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a) return arrow; } -static QPolygonF calcLines(const QStyleOptionSlider *dial, const QWidget *) -{ - QPolygonF poly; - int width = dial->rect.width(); - int height = dial->rect.height(); - qreal r = qMin(width, height) / 2; - int bigLineSize = calcBigLineSize(int(r)); - - qreal xc = width / 2; - qreal yc = height / 2; - int ns = dial->tickInterval; - int notches = (dial->maximum + ns - 1 - dial->minimum) / ns; - if (notches <= 0) - return poly; - if (dial->maximum < dial->minimum - || dial->maximum - dial->minimum > 1000) { - int maximum = dial->minimum + 1000; - notches = (maximum + ns - 1 - dial->minimum) / ns; - } - - poly.resize(2 + 2 * notches); - int smallLineSize = bigLineSize / 2; - for (int i = 0; i <= notches; ++i) { - qreal angle = dial->dialWrapping ? Q_PI * 3 / 2 - i * 2 * Q_PI / notches - : (Q_PI * 8 - i * 10 * Q_PI / notches) / 6; - qreal s = qSin(angle); - qreal c = qCos(angle); - if (i == 0 || (((ns * i) % (dial->pageStep ? dial->pageStep : 1)) == 0)) { - poly[2 * i] = QPointF(xc + (r - bigLineSize) * c, - yc - (r - bigLineSize) * s); - poly[2 * i + 1] = QPointF(xc + r * c, yc - r * s); - } else { - poly[2 * i] = QPointF(xc + (r - 1 - smallLineSize) * c, - yc - (r - 1 - smallLineSize) * s); - poly[2 * i + 1] = QPointF(xc + (r - 1) * c, yc -(r - 1) * s); - } - } - return poly; -} #endif // QT_NO_DIAL /*! @@ -3794,7 +3715,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl // draw notches if (dial->subControls & QStyle::SC_DialTickmarks) { p->setPen(pal.foreground().color()); - p->drawLines(calcLines(dial, widget)); // ### calcLines could be cached... + p->drawLines(QStyleHelper::calcLines(dial)); } if (dial->state & State_Enabled) { @@ -3816,7 +3737,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl p->setBrush(pal.button()); p->drawPolygon(arrow); - a = angle(QPointF(width / 2, height / 2), arrow[0]); + a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]); p->setBrush(Qt::NoBrush); if (a <= 0 || a > 200) { diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 08d6fed..9acf42c 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -50,6 +50,7 @@ #include <private/qpaintengine_mac_p.h> #include <private/qpainter_p.h> #include <private/qprintengine_mac_p.h> +#include <private/qstylehelper_p.h> #include <qapplication.h> #include <qbitmap.h> #include <qcheckbox.h> @@ -3888,13 +3889,16 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } break; case CE_TabBarTabShape: - if (const QStyleOptionTabV3 *tabOpt = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { - if (tabOpt->documentMode) { - p->save(); - QRect tabRect = tabOpt->rect; - drawTabShape(p, tabOpt); - p->restore(); - return; + if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(opt)) { + + if (const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { + if (tabOptV3->documentMode) { + p->save(); + QRect tabRect = tabOptV3->rect; + drawTabShape(p, tabOptV3); + p->restore(); + return; + } } #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) @@ -5375,6 +5379,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex } } break; + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt)) + QStyleHelper::drawDial(dial, p); + break; default: QWindowsStyle::drawComplexControl(cc, opt, p, widget); break; diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index 24d7748..66464ff 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -51,6 +51,7 @@ static const int ProgressBarFps = 25; static const int blueFrameWidth = 2; // with of line edit focus frame #include "qwindowsstyle_p.h" +#include <private/qstylehelper_p.h> #include <qapplication.h> #include <qbitmap.h> #include <qabstractitemview.h> @@ -4970,6 +4971,12 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt painter->restore(); } break; +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option)) + QStyleHelper::drawDial(dial, painter); + break; +#endif // QT_NO_DIAL default: QWindowsStyle::drawComplexControl(control, option, painter, widget); break; diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp new file mode 100644 index 0000000..79a1075 --- /dev/null +++ b/src/gui/styles/qstylehelper.cpp @@ -0,0 +1,295 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstylehelper_p.h" + +#include <qstyleoption.h> +#include <qpainter.h> +#include <qpixmapcache.h> +#include <private/qmath_p.h> +#include <private/qstyle_p.h> +#include <qmath.h> + +QT_BEGIN_NAMESPACE + +const bool QStyleHelper::UsePixmapCache = true; + +QString QStyleHelper::uniqueName(const QString &key, const QStyleOption *option, const QSize &size) +{ + QString tmp; + const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option); + tmp.sprintf("%s-%d-%d-%lld-%dx%d-%d", key.toLatin1().constData(), uint(option->state), + complexOption ? uint(complexOption->activeSubControls) : uint(0), + option->palette.cacheKey(), size.width(), size.height(), option->direction); +#ifndef QT_NO_SPINBOX + if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { + tmp.append(QLatin1Char('-')); + tmp.append(QString::number(spinBox->buttonSymbols)); + tmp.append(QLatin1Char('-')); + tmp.append(QString::number(spinBox->stepEnabled)); + tmp.append(QLatin1Char('-')); + tmp.append(QLatin1Char(spinBox->frame ? '1' : '0')); + } +#endif // QT_NO_SPINBOX + return tmp; +} + +#ifndef QT_NO_DIAL + +int QStyleHelper::calcBigLineSize(int radius) +{ + int bigLineSize = radius / 6; + if (bigLineSize < 4) + bigLineSize = 4; + if (bigLineSize > radius / 2) + bigLineSize = radius / 2; + return bigLineSize; +} + +static QPointF calcRadialPos(const QStyleOptionSlider *dial, float offset) +{ + const int width = dial->rect.width(); + const int height = dial->rect.height(); + const int r = qMin(width, height) / 2; + const int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition); + float a = 0; + if (dial->maximum == dial->minimum) + a = Q_PI / 2; + else if (dial->dialWrapping) + a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI + / (dial->maximum - dial->minimum); + else + a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI + / (dial->maximum - dial->minimum)) / 6; + float xc = width / 2.0; + float yc = height / 2.0; + float len = r - QStyleHelper::calcBigLineSize(r) - 3; + float back = offset * len; + QPointF pos(QPointF(xc + back * qCos(a), yc - back * qSin(a))); + return pos; +} + +qreal QStyleHelper::angle(const QPointF &p1, const QPointF &p2) +{ + static const qreal rad_factor = 180 / Q_PI; + qreal _angle = 0; + + if (p1.x() == p2.x()) { + if (p1.y() < p2.y()) + _angle = 270; + else + _angle = 90; + } else { + qreal x1, x2, y1, y2; + + if (p1.x() <= p2.x()) { + x1 = p1.x(); y1 = p1.y(); + x2 = p2.x(); y2 = p2.y(); + } else { + x2 = p1.x(); y2 = p1.y(); + x1 = p2.x(); y1 = p2.y(); + } + + qreal m = -(y2 - y1) / (x2 - x1); + _angle = atan(m) * rad_factor; + + if (p1.x() < p2.x()) + _angle = 180 - _angle; + else + _angle = -_angle; + } + return _angle; +} + +QPolygonF QStyleHelper::calcLines(const QStyleOptionSlider *dial) +{ + QPolygonF poly; + int width = dial->rect.width(); + int height = dial->rect.height(); + qreal r = qMin(width, height) / 2; + int bigLineSize = calcBigLineSize(int(r)); + + qreal xc = width / 2 + 0.5; + qreal yc = height / 2 + 0.5; + int ns = dial->tickInterval; + int notches = (dial->maximum + ns - 1 - dial->minimum) / ns; + if (notches <= 0) + return poly; + if (dial->maximum < dial->minimum || dial->maximum - dial->minimum > 1000) { + int maximum = dial->minimum + 1000; + notches = (maximum + ns - 1 - dial->minimum) / ns; + } + + poly.resize(2 + 2 * notches); + int smallLineSize = bigLineSize / 2; + for (int i = 0; i <= notches; ++i) { + qreal angle = dial->dialWrapping ? Q_PI * 3 / 2 - i * 2 * Q_PI / notches + : (Q_PI * 8 - i * 10 * Q_PI / notches) / 6; + qreal s = qSin(angle); + qreal c = qCos(angle); + if (i == 0 || (((ns * i) % (dial->pageStep ? dial->pageStep : 1)) == 0)) { + poly[2 * i] = QPointF(xc + (r - bigLineSize) * c, + yc - (r - bigLineSize) * s); + poly[2 * i + 1] = QPointF(xc + r * c, yc - r * s); + } else { + poly[2 * i] = QPointF(xc + (r - 1 - smallLineSize) * c, + yc - (r - 1 - smallLineSize) * s); + poly[2 * i + 1] = QPointF(xc + (r - 1) * c, yc -(r - 1) * s); + } + } + return poly; +} + + +// This will draw a nice and shiny QDial for us. We don't want +// all the shinyness in QWindowsStyle, hence we place it here + +void QStyleHelper::drawDial(const QStyleOptionSlider *option, QPainter *painter) +{ + QPalette pal = option->palette; + QColor buttonColor = pal.button().color(); + const int width = option->rect.width(); + const int height = option->rect.height(); + const bool enabled = option->state & QStyle::State_Enabled; + qreal r = qMin(width, height) / 2; + r -= r/50; + const qreal penSize = r/20.0; + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + // Draw notches + if (option->subControls & QStyle::SC_DialTickmarks) { + painter->setPen(option->palette.dark().color().darker(120)); + painter->drawLines(QStyleHelper::calcLines(option)); + } + + // Cache dial background + BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial")); + p->setRenderHint(QPainter::Antialiasing); + + const qreal d_ = r / 6; + const qreal dx = option->rect.x() + d_ + (width - 2 * r) / 2 + 1; + const qreal dy = option->rect.y() + d_ + (height - 2 * r) / 2 + 1; + + QRectF br = QRectF(dx + 0.5, dy + 0.5, + int(r * 2 - 2 * d_ - 2), + int(r * 2 - 2 * d_ - 2)); + buttonColor.setHsv(buttonColor .hue(), + qMin(140, buttonColor .saturation()), + qMax(180, buttonColor.value())); + QColor shadowColor(0, 0, 0, 20); + + if (enabled) { + // Drop shadow + qreal shadowSize = qMax(1.0, penSize/2.0); + QRectF shadowRect= br.adjusted(-2*shadowSize, -2*shadowSize, + 2*shadowSize, 2*shadowSize); + QRadialGradient shadowGradient(shadowRect.center().x(), + shadowRect.center().y(), shadowRect.width()/2.0, + shadowRect.center().x(), shadowRect.center().y()); + shadowGradient.setColorAt(0.91, QColor(0, 0, 0, 40)); + shadowGradient.setColorAt(1.0, Qt::transparent); + p->setBrush(shadowGradient); + p->setPen(Qt::NoPen); + p->translate(shadowSize, shadowSize); + p->drawEllipse(shadowRect); + p->translate(-shadowSize, -shadowSize); + + // Main gradient + QRadialGradient gradient(br.center().x() - br.width()/3, dy, + br.width()*1.3, br.center().x(), + br.center().y() - br.height()/2); + gradient.setColorAt(0, buttonColor.lighter(110)); + gradient.setColorAt(0.5, buttonColor); + gradient.setColorAt(0.501, buttonColor.darker(102)); + gradient.setColorAt(1, buttonColor.darker(115)); + p->setBrush(gradient); + } else { + p->setBrush(Qt::NoBrush); + } + + p->setPen(QPen(buttonColor.darker(280))); + p->drawEllipse(br); + p->setBrush(Qt::NoBrush); + p->setPen(buttonColor.lighter(110)); + p->drawEllipse(br.adjusted(1, 1, -1, -1)); + if (option->state & QStyle::State_HasFocus) { + QColor highlight = pal.highlight().color(); + highlight.setHsv(highlight.hue(), + qMin(160, highlight.saturation()), + qMax(230, highlight.value())); + highlight.setAlpha(127); + p->setPen(QPen(highlight, 2.0)); + p->setBrush(Qt::NoBrush); + p->drawEllipse(br.adjusted(-1, -1, 1, 1)); + } + + END_STYLE_PIXMAPCACHE + + QPointF dp = calcRadialPos(option, 0.70); + buttonColor = buttonColor.lighter(104); + buttonColor.setAlphaF(0.8); + const float ds = r/7.0; + QRectF dialRect(dp.x() - ds, dp.y() - ds, 2*ds, 2*ds); + QRadialGradient dialGradient(dialRect.center().x() + dialRect.width()/2, + dialRect.center().y() + dialRect.width(), + dialRect.width()*2, + dialRect.center().x(), dialRect.center().y()); + dialGradient.setColorAt(1, buttonColor.darker(130)); + dialGradient.setColorAt(0.201, buttonColor.darker(105)); + dialGradient.setColorAt(0.2, buttonColor.darker(104)); + dialGradient.setColorAt(0, buttonColor.darker(102)); + + painter->setBrush(dialGradient); + painter->setPen(QColor(255, 255, 255, 150)); + painter->drawEllipse(dialRect.adjusted(-1, -1, 1, 1)); + painter->setPen(QColor(0, 0, 0, 50)); + painter->drawEllipse(dialRect); + if (penSize > 3.0) { + painter->setPen(QPen(QColor(0, 0, 0, 16), penSize/2.0)); + painter->drawLine(calcRadialPos(option, 0.95), calcRadialPos(option, 0.97)); + } + painter->restore(); +} +#endif //QT_NO_DIAL + +QT_END_NAMESPACE diff --git a/src/gui/styles/qstylehelper_p.h b/src/gui/styles/qstylehelper_p.h new file mode 100644 index 0000000..d9b2e28 --- /dev/null +++ b/src/gui/styles/qstylehelper_p.h @@ -0,0 +1,39 @@ +#include <QtCore/qglobal.h> +#include <QtCore/qpoint.h> +#include <QtGui/qpolygon.h> + +#ifndef QSTYLEHELPER_P_H +#define QSTYLEHELPER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QPainter; +class QStyleOptionSlider; +class QStyleOption; + +namespace QStyleHelper +{ + extern const bool UsePixmapCache; + QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size); +#ifndef QT_NO_DIAL + qreal angle(const QPointF &p1, const QPointF &p2); + QPolygonF calcLines(const QStyleOptionSlider *dial); + int calcBigLineSize(int radius); + void drawDial(const QStyleOptionSlider *dial, QPainter *painter); +#endif //QT_NO_DIAL +} + +QT_END_NAMESPACE + +#endif // QSTYLEHELPER_P_H diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index f22cd56..a39eeb7 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -2916,6 +2916,10 @@ void QStyleSheetStyle::polish(QWidget *w) if (ew->autoFillBackground()) { ew->setAutoFillBackground(false); autoFillDisabledWidgets->insert(w); + if (ew != w) { //eg. viewport of a scrollarea + //(in order to draw the background anyway in case we don't.) + ew->setAttribute(Qt::WA_StyledBackground, true); + } } if (!rule.hasBackground() || rule.background()->isTransparent() || rule.hasBox() || (!rule.hasNativeBorder() && !rule.border()->isOpaque())) @@ -4345,8 +4349,16 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op return; case PE_Widget: - if (!rule.hasBackground()) + if (!rule.hasBackground()) { + QWidget *container = containerWidget(w); + if (autoFillDisabledWidgets->contains(container) + && (container == w || !renderRule(container, opt).hasBackground())) { + //we do not have a background, but we disabled the autofillbackground anyway. so fill the background now. + // (this may happen if we have rules like :focus) + p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole())); + } break; + } #ifndef QT_NO_SCROLLAREA if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) { diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 00c3f99..bf3a3cb 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -67,6 +67,9 @@ #include "qpixmapcache.h" #include "qwizard.h" #include "qlistview.h" +#include <private/qmath_p.h> +#include <qmath.h> + #ifdef Q_WS_X11 #include "qfileinfo.h" @@ -3177,6 +3180,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp } break; #endif // QT_NO_SPINBOX + default: QCommonStyle::drawComplexControl(cc, opt, p, widget); } diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 9d735a7..55f99a3 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -46,6 +46,7 @@ #include <private/qobject_p.h> #include <private/qpaintengine_raster_p.h> #include <private/qapplication_p.h> +#include <private/qstylehelper_p.h> #include <qlibrary.h> #include <qpainter.h> #include <qpaintengine.h> @@ -3164,6 +3165,12 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } break; #endif //QT_NO_WORKSPACE +#ifndef QT_NO_DIAL + case CC_Dial: + if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option)) + QStyleHelper::drawDial(dial, painter); + break; +#endif // QT_NO_DIAL default: QWindowsStyle::drawComplexControl(cc, option, p, widget); break; diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri index 376f834..2164e1e 100644 --- a/src/gui/styles/styles.pri +++ b/src/gui/styles/styles.pri @@ -7,12 +7,14 @@ HEADERS += \ styles/qstyleplugin.h \ styles/qcommonstylepixmaps_p.h \ styles/qcommonstyle.h \ + styles/qstylehelper_p.h \ styles/qstylesheetstyle_p.h SOURCES += \ styles/qstyle.cpp \ styles/qstylefactory.cpp \ styles/qstyleoption.cpp \ styles/qstyleplugin.cpp \ + styles/qstylehelper.cpp \ styles/qcommonstyle.cpp \ styles/qstylesheetstyle.cpp \ styles/qstylesheetstyle_default.cpp diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index c337783..9c3d6c2 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -287,6 +287,7 @@ public: private: Q_DISABLE_COPY(QTextDocument) Q_DECLARE_PRIVATE(QTextDocument) + friend class QTextObjectPrivate; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QTextDocument::FindFlags) diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 320ecbf..05ddf47 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -1484,7 +1484,6 @@ QTextObject *QTextDocumentPrivate::createObject(const QTextFormat &f, int object QTextObject *obj = document()->createObject(f); if (obj) { - obj->d_func()->pieceTable = this; obj->d_func()->objectIndex = objectIndex == -1 ? formats.createObjectIndex(f) : objectIndex; objects[obj->d_func()->objectIndex] = obj; } diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index e305027..d1a3361 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -50,6 +50,11 @@ QT_BEGIN_NAMESPACE class QTextListPrivate : public QTextBlockGroupPrivate { +public: + QTextListPrivate(QTextDocument *doc) + : QTextBlockGroupPrivate(doc) + { + } }; /*! @@ -111,7 +116,7 @@ class QTextListPrivate : public QTextBlockGroupPrivate /*! \internal */ QTextList::QTextList(QTextDocument *doc) - : QTextBlockGroup(*new QTextListPrivate, doc) + : QTextBlockGroup(*new QTextListPrivate(doc), doc) { } diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index 1645a21..3f4c8e5 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -88,7 +88,7 @@ QT_BEGIN_NAMESPACE from QTextDocument::createObject(). */ QTextObject::QTextObject(QTextDocument *doc) - : QObject(*new QTextObjectPrivate, doc) + : QObject(*new QTextObjectPrivate(doc), doc) { } @@ -98,7 +98,7 @@ QTextObject::QTextObject(QTextDocument *doc) \internal */ QTextObject::QTextObject(QTextObjectPrivate &p, QTextDocument *doc) - :QObject(p, doc) + : QObject(p, doc) { } @@ -221,7 +221,7 @@ void QTextBlockGroupPrivate::markBlocksDirty() QTextDocument::createObject(). */ QTextBlockGroup::QTextBlockGroup(QTextDocument *doc) - : QTextObject(*new QTextBlockGroupPrivate, doc) + : QTextObject(*new QTextBlockGroupPrivate(doc), doc) { } @@ -410,7 +410,7 @@ QTextFrameLayoutData::~QTextFrameLayoutData() Creates a new empty frame for the text \a document. */ QTextFrame::QTextFrame(QTextDocument *doc) - : QTextObject(*new QTextFramePrivate, doc) + : QTextObject(*new QTextFramePrivate(doc), doc) { Q_D(QTextFrame); d->fragment_start = 0; diff --git a/src/gui/text/qtextobject_p.h b/src/gui/text/qtextobject_p.h index b00a16a..dd05eb4 100644 --- a/src/gui/text/qtextobject_p.h +++ b/src/gui/text/qtextobject_p.h @@ -55,6 +55,7 @@ #include "QtGui/qtextobject.h" #include "private/qobject_p.h" +#include "QtGui/qtextdocument.h" QT_BEGIN_NAMESPACE @@ -64,6 +65,10 @@ class QTextObjectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QTextObject) public: + QTextObjectPrivate(QTextDocument *doc) + : pieceTable(doc->d_func()), objectIndex(-1) + { + } QTextDocumentPrivate *pieceTable; int objectIndex; }; @@ -72,7 +77,10 @@ class QTextBlockGroupPrivate : public QTextObjectPrivate { Q_DECLARE_PUBLIC(QTextBlockGroup) public: - + QTextBlockGroupPrivate(QTextDocument *doc) + : QTextObjectPrivate(doc) + { + } typedef QList<QTextBlock> BlockList; BlockList blocks; void markBlocksDirty(); @@ -85,7 +93,10 @@ class QTextFramePrivate : public QTextObjectPrivate friend class QTextDocumentPrivate; Q_DECLARE_PUBLIC(QTextFrame) public: - + QTextFramePrivate(QTextDocument *doc) + : QTextObjectPrivate(doc) + { + } virtual void fragmentAdded(const QChar &type, uint fragment); virtual void fragmentRemoved(const QChar &type, uint fragment); void remove_me(); diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp index 375bb09..ba1c04f 100644 --- a/src/gui/text/qtexttable.cpp +++ b/src/gui/text/qtexttable.cpp @@ -553,7 +553,7 @@ void QTextTablePrivate::update() const /*! \internal */ QTextTable::QTextTable(QTextDocument *doc) - : QTextFrame(*new QTextTablePrivate, doc) + : QTextFrame(*new QTextTablePrivate(doc), doc) { } diff --git a/src/gui/text/qtexttable_p.h b/src/gui/text/qtexttable_p.h index 1ba3a3f..f2b45b6 100644 --- a/src/gui/text/qtexttable_p.h +++ b/src/gui/text/qtexttable_p.h @@ -62,7 +62,7 @@ class QTextTablePrivate : public QTextFramePrivate { Q_DECLARE_PUBLIC(QTextTable) public: - QTextTablePrivate() : grid(0), nRows(0), dirty(true), blockFragmentUpdates(false) {} + QTextTablePrivate(QTextDocument *document) : QTextFramePrivate(document), grid(0), nRows(0), dirty(true), blockFragmentUpdates(false) {} ~QTextTablePrivate(); static QTextTable *createTable(QTextDocumentPrivate *, int pos, int rows, int cols, const QTextTableFormat &tableFormat); diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index b03df9e..e243ad0 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -3523,6 +3523,8 @@ void QLineEditPrivate::redo() { case RemoveSelection: case DeleteSelection: text.remove(cmd.pos, 1); + selstart = cmd.selStart; + selend = cmd.selEnd; cursor = cmd.pos; break; case Separator: diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp index 01ab884..1c4df93 100644 --- a/src/gui/widgets/qtextedit.cpp +++ b/src/gui/widgets/qtextedit.cpp @@ -1478,7 +1478,12 @@ void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e) layout->setViewport(QRect()); } -/*! \warning The underlying text document must not be modified from within a reimplementation +/*! \fn void QTextEdit::paintEvent(QPaintEvent *event) + +This event handler can be reimplemented in a subclass to receive paint events passed in \a event. +It is usually unnecessary to reimplement this function in a subclass of QTextEdit. + +\warning The underlying text document must not be modified from within a reimplementation of this function. */ void QTextEdit::paintEvent(QPaintEvent *e) diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index fc43369..b225c17 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -435,7 +435,7 @@ void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol prot The class also supports common predefined addresses: \l Null, \l LocalHost, \l LocalHostIPv6, \l Broadcast, and \l Any. - \sa QTcpSocket, QTcpServer, QUdpSocket + \sa QHostInfo, QTcpSocket, QTcpServer, QUdpSocket */ /*! \enum QHostAddress::SpecialAddress diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index f332a50..976a021 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -5328,6 +5328,9 @@ void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const q_vertexType * Q_Q(QOpenGLPaintEngine); QGL_FUNC_CONTEXT; + if (current_style == Qt::NoBrush) + return; + DEBUG_ONCE qDebug() << "QOpenGLPaintEnginePrivate: Using compositing program: fragment_brush =" << fragment_brush << ", fragment_composition_mode =" << fragment_composition_mode; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp index 8a30ad4..8dbad53 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp @@ -64,8 +64,6 @@ void QDirectFBPaintDevice::lockDirectFB() { void *mem; int w, h; - DFBSurfacePixelFormat format; - DFBResult result = dfbSurface->Lock(dfbSurface, DSLF_WRITE, &mem, &bpl); if (result != DFB_OK || !mem) { DirectFBError("QDirectFBPixmapData::buffer()", result); @@ -73,10 +71,8 @@ void QDirectFBPaintDevice::lockDirectFB() { } dfbSurface->GetSize(dfbSurface, &w, &h); - dfbSurface->GetPixelFormat(dfbSurface, &format); - lockedImage = new QImage(static_cast<uchar*>(mem), w, h, bpl, - QDirectFBScreen::getImageFormat(format)); + QDirectFBScreen::getImageFormat(dfbSurface)); } @@ -102,9 +98,7 @@ void* QDirectFBPaintDevice::memory() const QImage::Format QDirectFBPaintDevice::format() const { - DFBSurfacePixelFormat dfbFormat; - dfbSurface->GetPixelFormat(dfbSurface, &dfbFormat); - return QDirectFBScreen::getImageFormat(dfbFormat); + return QDirectFBScreen::getImageFormat(dfbSurface); } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 86357e6..84a92d8 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -112,7 +112,7 @@ CachedImage::CachedImage(const QImage &image) description = QDirectFBScreen::getSurfaceDescription(image); QDirectFBScreen* screen = QDirectFBScreen::instance(); - tmpSurface = screen->createDFBSurface(&description); + tmpSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); if (!tmpSurface) { qWarning("CachedImage CreateSurface failed!"); return; @@ -124,7 +124,7 @@ CachedImage::CachedImage(const QImage &image) description.flags = DFBSurfaceDescriptionFlags(description.flags & ~DSDESC_PREALLOCATED); - s = screen->createDFBSurface(&description); + s = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); if (!s) qWarning("QDirectFBPaintEngine failed caching image"); @@ -159,7 +159,7 @@ IDirectFBSurface* SurfaceCache::getSurface(const uint *buf, int size) DFBSurfaceDescription description; description = QDirectFBScreen::getSurfaceDescription(buf, size); - surface = QDirectFBScreen::instance()->createDFBSurface(&description); + surface = QDirectFBScreen::instance()->createDFBSurface(&description, QDirectFBScreen::TrackSurface); if (!surface) qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface"); @@ -724,13 +724,10 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, const QRectF &src) { QImage image = srcImage; - if (QDirectFBScreen::getSurfacePixelFormat(image) == DSPF_UNKNOWN) { - QImage::Format format; - if (image.hasAlphaChannel()) - format = QImage::Format_ARGB32_Premultiplied; - else - format = QImage::Format_RGB32; - image = image.convertToFormat(format); + if (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN) { + image = image.convertToFormat(image.hasAlphaChannel() + ? QDirectFBScreen::instance()->alphaPixmapFormat() + : QDirectFBScreen::instance()->pixelFormat()); } CachedImage *img = imageCache[image.cacheKey()]; @@ -756,7 +753,8 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, DFBSurfaceDescription description; description = QDirectFBScreen::getSurfaceDescription(image); - imgSurface = QDirectFBScreen::instance()->createDFBSurface(&description); + imgSurface = QDirectFBScreen::instance()->createDFBSurface(&description, + QDirectFBScreen::DontTrackSurface); if (!imgSurface) { qWarning("QDirectFBPaintEnginePrivate::drawImage"); return; @@ -790,8 +788,10 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, } if (changeFlags) surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags)); - if (doRelease) - QDirectFBScreen::instance()->releaseDFBSurface(imgSurface); + if (doRelease) { + surface->ReleaseSource(surface); + imgSurface->Release(imgSurface); + } } void QDirectFBPaintEnginePrivate::updateClip() @@ -1092,11 +1092,11 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp); } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) { - QImage* img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); + const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); + d->lock(); QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType); data->fromImage(*img, Qt::AutoColor); const QPixmap pix(data); - d->lock(); QRasterPaintEngine::drawTiledPixmap(r, pix, sp); } else { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 6352652..6d942a4 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -72,14 +72,19 @@ void QDirectFBPixmapData::resize(int width, int height) } DFBSurfaceDescription description; - description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | - DSDESC_HEIGHT); + description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH + | DSDESC_HEIGHT + | DSDESC_PIXELFORMAT); + QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, screen->pixelFormat()); description.width = width; description.height = height; - dfbSurface = screen->createDFBSurface(&description); - if (!dfbSurface) - qCritical("QDirectFBPixmapData::resize(): Unable to allocate surface"); + dfbSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); + if (!dfbSurface) { + setSerialNumber(0); + qWarning("QDirectFBPixmapData::resize(): Unable to allocate surface"); + return; + } setSerialNumber(++global_ser_no); } @@ -87,61 +92,15 @@ void QDirectFBPixmapData::resize(int width, int height) void QDirectFBPixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags) { - QImage image; - if (QDirectFBScreen::getSurfacePixelFormat(img) == DSPF_UNKNOWN) - image = img.convertToFormat(QImage::Format_ARGB32_Premultiplied); - else - image = img; - - DFBSurfaceDescription description; - description = QDirectFBScreen::getSurfaceDescription(image); - -#ifndef QT_NO_DIRECTFB_PREALLOCATED - IDirectFBSurface *imgSurface; - imgSurface = screen->createDFBSurface(&description); - if (!imgSurface) { - qWarning("QDirectFBPixmapData::fromImage()"); - setSerialNumber(0); - return; - } -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(imgSurface, image); -#endif -#endif // QT_NO_DIRECTFB_PREALLOCATED - - description.flags = DFBSurfaceDescriptionFlags(description.flags - & ~DSDESC_PREALLOCATED); - dfbSurface = screen->createDFBSurface(&description); + dfbSurface = screen->copyToDFBSurface(img, + img.hasAlphaChannel() ? screen->alphaPixmapFormat() + : screen->pixelFormat(), + QDirectFBScreen::TrackSurface); if (!dfbSurface) { qWarning("QDirectFBPixmapData::fromImage()"); setSerialNumber(0); return; } - -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(dfbSurface, image); -#endif - -#ifdef QT_NO_DIRECTFB_PREALLOCATED - char *mem; - surface->Lock(surface, DSLF_WRITE, (void**)&mem, &bpl); - const int w = image.width() * image.depth() / 8; - for (int i = 0; i < image.height(); ++i) { - memcpy(mem, image.scanLine(i), w); - mem += bpl; - } - surface->Unlock(surface); -#else - DFBResult result; - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); - result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); - if (result != DFB_OK) - DirectFBError("QDirectFBPixmapData::fromImage()", result); - dfbSurface->Flip(dfbSurface, 0, DSFLIP_NONE); - dfbSurface->ReleaseSource(dfbSurface); - screen->releaseDFBSurface(imgSurface); -#endif // QT_NO_DIRECTFB_PREALLOCATED - setSerialNumber(++global_ser_no); } @@ -161,30 +120,24 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) description.width = rect.width(); description.height = rect.height(); src->GetPixelFormat(src, &description.pixelformat); + src->GetCapabilities(src, &description.caps); - dfbSurface = screen->createDFBSurface(&description); + dfbSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); if (!dfbSurface) { qWarning("QDirectFBPixmapData::copy()"); setSerialNumber(0); return; } - DFBResult result; -#ifndef QT_NO_DIRECTFB_PALETTE - IDirectFBPalette *palette; - result = src->GetPalette(src, &palette); - if (result == DFB_OK) { - dfbSurface->SetPalette(dfbSurface, palette); - palette->Release(palette); - } -#endif - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); const DFBRectangle blitRect = { rect.x(), rect.y(), rect.width(), rect.height() }; - result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0); - if (result != DFB_OK) + DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0); + if (result != DFB_OK) { DirectFBError("QDirectFBPixmapData::copy()", result); + setSerialNumber(0); + return; + } setSerialNumber(++global_ser_no); } @@ -198,37 +151,16 @@ void QDirectFBPixmapData::fill(const QColor &color) Q_ASSERT(dfbSurface); if (color.alpha() < 255 && !hasAlphaChannel()) { - // convert to surface supporting alpha channel - DFBSurfacePixelFormat format; - dfbSurface->GetPixelFormat(dfbSurface, &format); - switch (format) { - case DSPF_YUY2: - case DSPF_UYVY: - format = DSPF_AYUV; - break; -#if (Q_DIRECTFB_VERSION >= 0x010100) - case DSPF_RGB444: - format = DSPF_ARGB4444; - break; - case DSPF_RGB555: -#endif - case DSPF_RGB18: - format = DSPF_ARGB6666; - break; - default: - format = DSPF_ARGB; - break; - } - DFBSurfaceDescription description; description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT); dfbSurface->GetSize(dfbSurface, &description.width, &description.height); - description.pixelformat = format; + QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, screen->alphaPixmapFormat()); screen->releaseDFBSurface(dfbSurface); // release old surface - dfbSurface = screen->createDFBSurface(&description); + dfbSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface); + setSerialNumber(++global_ser_no); if (!dfbSurface) { qWarning("QDirectFBPixmapData::fill()"); setSerialNumber(0); @@ -245,6 +177,10 @@ bool QDirectFBPixmapData::hasAlphaChannel() const if (!serialNumber()) return false; + // We don't need to ask DFB for this really. Can just keep track + // of what image format this has. It should always have either + // QDirectFBScreen::alphaPixmapFormat() or QScreen::pixelFormat() + DFBSurfacePixelFormat format; dfbSurface->GetPixelFormat(dfbSurface, &format); switch (format) { @@ -274,14 +210,12 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, { QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this); const QImage *image = that->buffer(); - if (image) { // avoid deep copy - const QImage transformed = image->transformed(transform, mode); - that->unlockDirectFB(); - QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType()); - data->fromImage(transformed, Qt::AutoColor); - return QPixmap(data); - } - return QPixmapData::transformed(transform, mode); + Q_ASSERT(image); + const QImage transformed = image->transformed(transform, mode); + that->unlockDirectFB(); + QDirectFBPixmapData *data = new QDirectFBPixmapData(QPixmapData::PixmapType); + data->fromImage(transformed, Qt::AutoColor); + return QPixmap(data); } int w, h; @@ -291,15 +225,14 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, if (size.isEmpty()) return QPixmap(); - QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType()); + QDirectFBPixmapData *data = new QDirectFBPixmapData(QPixmapData::PixmapType); data->resize(size.width(), size.height()); IDirectFBSurface *dest = data->dfbSurface; dest->SetBlittingFlags(dest, DSBLIT_NOFX); - const DFBRectangle srcRect = { 0, 0, w, h }; const DFBRectangle destRect = { 0, 0, size.width(), size.height() }; - dest->StretchBlit(dest, dfbSurface, &srcRect, &destRect); + dest->StretchBlit(dest, dfbSurface, 0, &destRect); return QPixmap(data); } @@ -309,39 +242,9 @@ QImage QDirectFBPixmapData::toImage() const if (!dfbSurface) return QImage(); -#ifdef QT_NO_DIRECTFB_PREALLOCATED QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this); const QImage *img = that->buffer(); - const QImage copied = img->copy(); - that->unlockDirectFB(); - return copied; -#else - - int w, h; - dfbSurface->GetSize(dfbSurface, &w, &h); - - // Always convert to ARGB32: - QImage image(w, h, QImage::Format_ARGB32); - - DFBSurfaceDescription description; - description = QDirectFBScreen::getSurfaceDescription(image); - - IDirectFBSurface *imgSurface = screen->createDFBSurface(&description); - if (!imgSurface) { - qWarning("QDirectFBPixmapData::toImage()"); - return QImage(); - } - - imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX); - DFBResult result = imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0); - if (result != DFB_OK) { - DirectFBError("QDirectFBPixmapData::toImage() blit failed", result); - return QImage(); - } - screen->releaseDFBSurface(imgSurface); - - return image; -#endif // QT_NO_DIRECTFB_PREALLOCATED + return img->copy(); } QPaintEngine* QDirectFBPixmapData::paintEngine() const diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 26c023f..db9672a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -81,6 +81,7 @@ public: QDirectFBKeyboardHandler *keyboard; #endif bool videoonly; + QImage::Format alphaPixmapFormat; }; QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen) @@ -96,6 +97,7 @@ QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen) , keyboard(0) #endif , videoonly(false) + , alphaPixmapFormat(QImage::Format_Invalid) { #ifndef QT_NO_QWS_SIGNALHANDLER QWSSignalHandler::instance()->addObject(this); @@ -130,7 +132,80 @@ QDirectFBScreenPrivate::~QDirectFBScreenPrivate() dfb->Release(dfb); } -IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription* desc, bool track) + + +// creates a preallocated surface with the same format as the image if +// possible. + +IDirectFBSurface* QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCreationOptions options) +{ + if (img.isNull()) // assert? + return 0; + if (QDirectFBScreen::getSurfacePixelFormat(img.format()) == DSPF_UNKNOWN) { + QImage image = img.convertToFormat(img.hasAlphaChannel() + ? d_ptr->alphaPixmapFormat + : pixelFormat()); + IDirectFBSurface *tmp = createDFBSurface(image, false); + if (!tmp) { + qWarning("Couldn't create surface createDFBSurface(QImage, bool)"); + return 0; + } + IDirectFBSurface *surface = copyDFBSurface(tmp, image.format(), options); + tmp->Release(tmp); + return surface; + } + + DFBSurfaceDescription desc = QDirectFBScreen::getSurfaceDescription(img); + IDirectFBSurface *surface = createDFBSurface(&desc, options); +#ifdef QT_NO_DIRECTFB_PREALLOCATED + if (surface) { + char *mem; + int bpl; + surface->Lock(dfbSurface, DSLF_WRITE, (void**)&mem, &bpl); + const int h = img.height(); + for (int i = 0; i < h; ++i) { + memcpy(mem, img.scanLine(i), bpl); + mem += bpl; + } + surface->Unlock(ret); + } +#endif +#ifndef QT_NO_DIRECTFB_PALETTE + if (img.numColors() != 0) + QDirectFBScreen::setSurfaceColorTable(surface, img); +#endif + return surface; +} + +IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src, + QImage::Format format, + SurfaceCreationOptions options) +{ + Q_ASSERT(src); + QSize size; + src->GetSize(src, &size.rwidth(), &size.rheight()); + IDirectFBSurface *surface = createDFBSurface(size, format, options); + surface->SetBlittingFlags(surface, DSBLIT_NOFX); + surface->Blit(surface, src, 0, 0, 0); + surface->ReleaseSource(surface); // ??? Is this always right? + return surface; +} + +IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, + QImage::Format format, + SurfaceCreationOptions options) +{ + DFBSurfaceDescription desc; + desc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH|DSDESC_HEIGHT); + if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format)) + return 0; + desc.width = size.width(); + desc.height = size.height(); + return createDFBSurface(&desc, options); +} + + +IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription *desc, SurfaceCreationOptions options) { DFBResult result; IDirectFBSurface* newSurface = 0; @@ -152,13 +227,18 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription* result = d_ptr->dfb->CreateSurface(d_ptr->dfb, desc, &newSurface); if (result != DFB_OK) { - DirectFBError("QDirectFBScreen::createDFBSurface", result); + qWarning("QDirectFBScreen::createDFBSurface() Failed!\n" + " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s", + desc->flags, desc->caps, desc->width, desc->height, + desc->pixelformat, DFB_PIXELFORMAT_INDEX(desc->pixelformat), + desc->preallocated[0].data, desc->preallocated[0].pitch, + DirectFBErrorString(result)); return 0; } Q_ASSERT(newSurface); - if (track) { + if (options & TrackSurface) { d_ptr->allocatedSurfaces.insert(newSurface); //qDebug("Created a new DirectFB surface at %p. New count = %d", @@ -168,8 +248,63 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription* return newSurface; } -void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface* surface) +IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, + QImage::Format format, + SurfaceCreationOptions options) { + QImage image = img; + const QImage::Format pixmapFormat = image.hasAlphaChannel() + ? QDirectFBScreen::alphaPixmapFormat() + : QDirectFBScreen::pixelFormat(); + + if (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN +#ifdef QT_NO_DIRECTFB_PREALLOCATED + || image.format() != pixmapFormat +#endif + ) { + image = image.convertToFormat(pixmapFormat); + } + + + IDirectFBSurface *dfbSurface = createDFBSurface(img.size(), format, options); + if (!dfbSurface) { + qWarning("QDirectFBPixmapData::fromImage() Couldn't create surface"); + return 0; + } + +#ifndef QT_NO_DIRECTFB_PREALLOCATED + IDirectFBSurface *imgSurface = createDFBSurface(img, DontTrackSurface); + if (!imgSurface) { + qWarning("QDirectFBPixmapData::fromImage()"); + QDirectFBScreen::releaseDFBSurface(dfbSurface); + return 0; + } + Q_ASSERT(imgSurface); + DFBResult result; + dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); + result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); + if (result != DFB_OK) + DirectFBError("QDirectFBPixmapData::fromImage()", result); + dfbSurface->ReleaseSource(dfbSurface); + imgSurface->Release(imgSurface); +#else // QT_NO_DIRECTFB_PREALLOCATED + Q_ASSERT(image.format() == pixmapFormat); + char *mem; + int bpl; + dfbSurface->Lock(dfbSurface, DSLF_WRITE, (void**)&mem, &bpl); + const int w = image.width() * image.depth() / 8; + for (int i = 0; i < image.height(); ++i) { + memcpy(mem, image.scanLine(i), w); + mem += bpl; + } + dfbSurface->Unlock(dfbSurface); +#endif + return dfbSurface; +} + +void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface *surface) +{ + Q_ASSERT(QDirectFBScreen::instance()); Q_ASSERT(surface); surface->Release(surface); if (!d_ptr->allocatedSurfaces.remove(surface)) @@ -200,9 +335,9 @@ IDirectFBDisplayLayer* QDirectFBScreen::dfbDisplayLayer() } #endif -DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(const QImage &image) +DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format format) { - switch (image.format()) { + switch (format) { #ifndef QT_NO_DIRECTFB_PALETTE case QImage::Format_Indexed8: return DSPF_LUT8; @@ -233,8 +368,21 @@ DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(const QImage &image }; } -QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format) +static inline bool isPremultiplied(IDirectFBSurface *surface) +{ + Q_ASSERT(surface); + DFBSurfaceCapabilities caps; + const DFBResult result = surface->GetCapabilities(surface, &caps); + Q_ASSERT(result == DFB_OK); + Q_UNUSED(result); + return caps & DSCAPS_PREMULTIPLIED; +} + +QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface) { + DFBSurfacePixelFormat format; + surface->GetPixelFormat(surface, &format); + switch (format) { case DSPF_LUT8: return QImage::Format_Indexed8; @@ -257,8 +405,14 @@ QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format) return QImage::Format_RGB666; case DSPF_RGB32: return QImage::Format_RGB32; - case DSPF_ARGB: - return QImage::Format_ARGB32_Premultiplied; + case DSPF_ARGB: { + DFBSurfaceCapabilities caps; + const DFBResult result = surface->GetCapabilities(surface, &caps); + Q_ASSERT(result == DFB_OK); + Q_UNUSED(result); + return (caps & DSCAPS_PREMULTIPLIED + ? QImage::Format_ARGB32_Premultiplied + : QImage::Format_ARGB32); } default: break; } @@ -268,38 +422,32 @@ QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format) DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const QImage &image) { DFBSurfaceDescription description; - DFBSurfacePixelFormat format = getSurfacePixelFormat(image); + + const DFBSurfacePixelFormat format = getSurfacePixelFormat(image.format()); if (format == DSPF_UNKNOWN || image.isNull()) { description.flags = DFBSurfaceDescriptionFlags(0); return description; } - description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS - | DSDESC_WIDTH + description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT - | DSDESC_PIXELFORMAT - | DSDESC_PREALLOCATED); - - description.caps = DSCAPS_NONE; +#ifndef QT_NO_DIRECTFB_PREALLOCATED + | DSDESC_PREALLOCATED +#endif + | DSDESC_PIXELFORMAT); + QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, image.format()); description.width = image.width(); description.height = image.height(); - description.pixelformat = format; +#ifndef QT_NO_DIRECTFB_PREALLOCATED description.preallocated[0].data = (void*)(image.bits()); description.preallocated[0].pitch = image.bytesPerLine(); description.preallocated[1].data = 0; description.preallocated[1].pitch = 0; +#endif - switch (image.format()) { - case QImage::Format_ARGB32_Premultiplied: - case QImage::Format_ARGB8565_Premultiplied: - case QImage::Format_ARGB6666_Premultiplied: - case QImage::Format_ARGB8555_Premultiplied: - case QImage::Format_ARGB4444_Premultiplied: + if (QDirectFBScreen::isPremultiplied(image.format())) description.caps = DSCAPS_PREMULTIPLIED; - default: - break; - } return description; } @@ -337,7 +485,7 @@ void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface, if (numColors == 0) return; - QVarLengthArray<DFBColor> colors(numColors); + QVarLengthArray<DFBColor, 256> colors(numColors); for (int i = 0; i < numColors; ++i) { QRgb c = image.color(i); colors[i].a = qAlpha(c); @@ -461,18 +609,10 @@ void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty) } else if (!image.isNull() && implicitHide) { show(); } + cursor = image.convertToFormat(QDirectFBScreen::instance()->alphaPixmapFormat()); if (!image.isNull()) { -#ifdef QT_NO_DIRECTFB_PALETTE - if (image.numColors() > 0) - cursor = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - else -#endif - if (image.format() == QImage::Format_Indexed8) { - cursor = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - } else { - cursor = image; - } + Q_ASSERT(cursor.numColors() == 0); size = cursor.size(); hotspot = QPoint(hotx, hoty); @@ -480,15 +620,12 @@ void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty) description = QDirectFBScreen::getSurfaceDescription(cursor); IDirectFBSurface *surface; - surface = QDirectFBScreen::instance()->createDFBSurface(&description); + surface = QDirectFBScreen::instance()->createDFBSurface(&description, + QDirectFBScreen::TrackSurface); if (!surface) { qWarning("QDirectFBScreenCursor::set: Unable to create surface"); return; } -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(surface, cursor); -#endif - DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); if (result != DFB_OK) { DirectFBError("QDirectFBScreenCursor::set: " @@ -636,7 +773,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec) } const QStringList displayArgs = displaySpec.split(QLatin1Char(':'), - QString::SkipEmptyParts); + QString::SkipEmptyParts); d_ptr->setFlipFlags(displayArgs); @@ -663,6 +800,12 @@ bool QDirectFBScreen::connect(const QString &displaySpec) description.caps = DFBSurfaceCapabilities(DSCAPS_PRIMARY | DSCAPS_DOUBLE | DSCAPS_STATIC_ALLOC); + if (displayArgs.contains(QLatin1String("forcepremultiplied"), + Qt::CaseInsensitive)) { + description.caps = DFBSurfaceCapabilities(description.caps + | DSCAPS_PREMULTIPLIED); + } + if (!(d_ptr->flipFlags & DSFLIP_BLIT)) { description.caps = DFBSurfaceCapabilities(description.caps | DSCAPS_DOUBLE @@ -671,12 +814,43 @@ bool QDirectFBScreen::connect(const QString &displaySpec) // We don't track the primary surface as it's released in disconnect - d_ptr->dfbSurface = createDFBSurface(&description, false); + d_ptr->dfbSurface = createDFBSurface(&description, DontTrackSurface); if (!d_ptr->dfbSurface) { DirectFBError("QDirectFBScreen: error creating primary surface", result); return false; } + + // Work out what format we're going to use for surfaces with an alpha channel + d_ptr->alphaPixmapFormat = QDirectFBScreen::getImageFormat(d_ptr->dfbSurface); + setPixelFormat(d_ptr->alphaPixmapFormat); + switch (d_ptr->alphaPixmapFormat) { + case QImage::Format_RGB666: + d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied; + break; + case QImage::Format_RGB444: + d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied; + break; + case QImage::NImageFormats: + case QImage::Format_Invalid: + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + case QImage::Format_Indexed8: + case QImage::Format_RGB32: + case QImage::Format_RGB888: + case QImage::Format_RGB16: + case QImage::Format_RGB555: + d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied; + break; + case QImage::Format_ARGB32: + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB4444_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB6666_Premultiplied: + // works already + break; + } d_ptr->dfbSurface->GetSize(d_ptr->dfbSurface, &w, &h); data = 0; @@ -692,7 +866,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec) else DirectFBError("QDirectFBScreen: error getting surface format", result); - setPixelFormat(getImageFormat(format)); + setPixelFormat(getImageFormat(d_ptr->dfbSurface)); physWidth = physHeight = -1; QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); @@ -954,21 +1128,14 @@ void QDirectFBScreen::exposeRegion(QRegion r, int changing) void QDirectFBScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion ®) { - IDirectFBSurface *src = 0; - DFBSurfaceDescription description = getSurfaceDescription(img); - - src = createDFBSurface(&description); + IDirectFBSurface *src = createDFBSurface(img, QDirectFBScreen::DontTrackSurface); if (!src) { qWarning("QDirectFBScreen::blit(): Error creating surface"); return; } -#ifndef QT_NO_DIRECTFB_PALETTE - setSurfaceColorTable(d_ptr->dfbSurface, img); -#endif - blit(src, topLeft, reg); - - releaseDFBSurface(src); + d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); + src->Release(src); } void QDirectFBScreen::blit(IDirectFBSurface *src, const QPoint &topLeft, @@ -1021,3 +1188,27 @@ void QDirectFBScreen::solidFill(const QColor &color, const QRegion ®ion) dfbRects.size()); } +QImage::Format QDirectFBScreen::alphaPixmapFormat() const +{ + return d_ptr->alphaPixmapFormat; +} + + +bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, + QImage::Format format) +{ + const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); + if (pixelformat == DSPF_UNKNOWN) + return false; + description->flags = DFBSurfaceDescriptionFlags(description->flags | DSDESC_PIXELFORMAT); + description->pixelformat = pixelformat; + if (QDirectFBScreen::isPremultiplied(format)) { + if (!(description->flags & DSDESC_CAPS)) { + description->caps = DSCAPS_PREMULTIPLIED; + description->flags = DFBSurfaceDescriptionFlags(description->flags | DSDESC_CAPS); + } else { + description->caps = DFBSurfaceCapabilities(description->caps | DSCAPS_PREMULTIPLIED); + } + } + return true; +} diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 35dea0d..a1e93c6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -88,18 +88,38 @@ public: #endif // Track surface creation/release so we can release all on exit - IDirectFBSurface* createDFBSurface(const DFBSurfaceDescription* desc, bool track = true); + enum SurfaceCreationOption { + DontTrackSurface = 0, + TrackSurface = 1 + }; + Q_DECLARE_FLAGS(SurfaceCreationOptions, SurfaceCreationOption); + IDirectFBSurface *createDFBSurface(const DFBSurfaceDescription *desc, + SurfaceCreationOptions options); + IDirectFBSurface *createDFBSurface(const QImage &image, + SurfaceCreationOptions options); + IDirectFBSurface *createDFBSurface(const QSize &size, + QImage::Format format, + SurfaceCreationOptions options); + IDirectFBSurface *copyDFBSurface(IDirectFBSurface *src, + QImage::Format format, + SurfaceCreationOptions options); + IDirectFBSurface *copyToDFBSurface(const QImage &image, + QImage::Format format, + SurfaceCreationOptions options); void releaseDFBSurface(IDirectFBSurface* surface); + bool preferVideoOnly() const; static int depth(DFBSurfacePixelFormat format); - static DFBSurfacePixelFormat getSurfacePixelFormat(const QImage &image); + static DFBSurfacePixelFormat getSurfacePixelFormat(QImage::Format format); static DFBSurfaceDescription getSurfaceDescription(const QImage &image); static DFBSurfaceDescription getSurfaceDescription(const uint *buffer, int length); - static QImage::Format getImageFormat(DFBSurfacePixelFormat format); + static QImage::Format getImageFormat(IDirectFBSurface *surface); + static bool initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, QImage::Format format); static inline bool isPremultiplied(QImage::Format format); + QImage::Format alphaPixmapFormat() const; #ifndef QT_NO_DIRECTFB_PALETTE static void setSurfaceColorTable(IDirectFBSurface *surface, @@ -114,6 +134,8 @@ private: QDirectFBScreenPrivate *d_ptr; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QDirectFBScreen::SurfaceCreationOptions); + inline bool QDirectFBScreen::isPremultiplied(QImage::Format format) { switch (format) { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index ce026ea..00d1781 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -153,8 +153,8 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) DSDESC_PIXELFORMAT); description.width = rect.width(); description.height = rect.height(); - description.pixelformat = DSPF_ARGB; - + QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, + QDirectFBSurface::instance()->pixelFormat()); dfbSurface = QDirectFBScreen::instance()->createDFBSurface(&description, false); } else { Q_ASSERT(dfbSurface); diff --git a/src/script/qscriptengine.cpp b/src/script/qscriptengine.cpp index d4e1923..d8908ed 100644 --- a/src/script/qscriptengine.cpp +++ b/src/script/qscriptengine.cpp @@ -1169,7 +1169,8 @@ bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr) bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr) { QScriptValueImpl impl = QScriptValuePrivate::valueOf(value); - return QScriptEnginePrivate::convert(impl, type, ptr, /*engine=*/0); + QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(value.engine()); + return QScriptEnginePrivate::convert(impl, type, ptr, eng_p); } /*! diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp index f7b2ae8..e822da5 100644 --- a/src/svg/qsvggenerator.cpp +++ b/src/svg/qsvggenerator.cpp @@ -516,7 +516,34 @@ public: \brief The QSvgGenerator class provides a paint device that is used to create SVG drawings. \reentrant - \sa QSvgRenderer, QSvgWidget + This paint device represents a Scalable Vector Graphics (SVG) drawing. Like QPrinter, it is + designed as a write-only device that generates output in a specific format. + + To write an SVG file, you first need to configure the output by setting the \l fileName + or \l outputDevice properties. It is usually necessary to specify the size of the drawing + by setting the \l size property, and in some cases where the drawing will be included in + another, the \l viewBox property also needs to be set. + + \snippet examples/painting/svggenerator/window.cpp configure SVG generator + + Other meta-data can be specified by setting the \a title, \a description and \a resolution + properties. + + As with other QPaintDevice subclasses, a QPainter object is used to paint onto an instance + of this class: + + \snippet examples/painting/svggenerator/window.cpp begin painting + \dots + \snippet examples/painting/svggenerator/window.cpp end painting + + Painting is performed in the same way as for any other paint device. However, + it is necessary to use the QPainter::begin() and \l{QPainter::}{end()} to + explicitly begin and end painting on the device. + + The \l{SVG Generator Example} shows how the same painting commands can be used + for painting a widget and writing an SVG file. + + \sa QSvgRenderer, QSvgWidget, {About SVG} */ /*! |