diff options
author | Gunnar Sletta <gunnar@trolltech.com> | 2009-11-04 06:38:36 (GMT) |
---|---|---|
committer | Gunnar Sletta <gunnar@trolltech.com> | 2009-11-04 06:38:36 (GMT) |
commit | 764f558846b8ee6f115004fc939b890991c40bfa (patch) | |
tree | 9bd47140cedbc9d8d28702618e6ad86fa6f2f666 /src/gui | |
parent | 9b0c0faf73dbdc382f1c02a42b10018bf9961d72 (diff) | |
parent | 1400ce5b85fbe7c67899f5f62bfd276eecb21ae0 (diff) | |
download | Qt-764f558846b8ee6f115004fc939b890991c40bfa.zip Qt-764f558846b8ee6f115004fc939b890991c40bfa.tar.gz Qt-764f558846b8ee6f115004fc939b890991c40bfa.tar.bz2 |
Merge branch '4.6' of c:\dev\qt-graphics-4.6
Conflicts:
tools/qdoc3/test/qt-build-docs.qdocconf
tools/qdoc3/test/qt-inc.qdocconf
Diffstat (limited to 'src/gui')
230 files changed, 6435 insertions, 4275 deletions
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp index 0ae79b6..1e9c166 100644 --- a/src/gui/animation/qguivariantanimation.cpp +++ b/src/gui/animation/qguivariantanimation.cpp @@ -54,10 +54,10 @@ QT_BEGIN_NAMESPACE template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress) { - return QColor(_q_interpolate(f.red(), t.red(), progress), - _q_interpolate(f.green(), t.green(), progress), - _q_interpolate(f.blue(), t.blue(), progress), - _q_interpolate(f.alpha(), t.alpha(), progress)); + return QColor(qBound(0,_q_interpolate(f.red(), t.red(), progress),255), + qBound(0,_q_interpolate(f.green(), t.green(), progress),255), + qBound(0,_q_interpolate(f.blue(), t.blue(), progress),255), + qBound(0,_q_interpolate(f.alpha(), t.alpha(), progress),255)); } template<> Q_INLINE_TEMPLATE QQuaternion _q_interpolate(const QQuaternion &f,const QQuaternion &t, qreal progress) diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index eab842f..c6b4a77 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -777,7 +777,7 @@ void QFileDialog::setDirectory(const QString &directory) QModelIndex root = d->model->setRootPath(newDirectory); d->qFileDialogUi->newFolderButton->setEnabled(d->model->flags(root) & Qt::ItemIsDropEnabled); if (root != d->rootIndex()) { -#ifndef QT_NO_COMPLETER +#ifndef QT_NO_FSCOMPLETER if (directory.endsWith(QLatin1Char('/'))) d->completer->setCompletionPrefix(newDirectory); else @@ -2177,12 +2177,12 @@ void QFileDialogPrivate::createWidgets() #ifndef QT_NO_SHORTCUT qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit); #endif -#ifndef QT_NO_COMPLETER +#ifndef QT_NO_FSCOMPLETER completer = new QFSCompleter(model, q); qFileDialogUi->fileNameEdit->setCompleter(completer); QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_autoCompleteFileName(QString))); -#endif // QT_NO_COMPLETER +#endif // QT_NO_FSCOMPLETER QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_updateOkButton())); @@ -2302,7 +2302,7 @@ void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel) proxyModel->setSourceModel(d->model); d->qFileDialogUi->listView->setModel(d->proxyModel); d->qFileDialogUi->treeView->setModel(d->proxyModel); -#ifndef QT_NO_COMPLETER +#ifndef QT_NO_FSCOMPLETER d->completer->setModel(d->proxyModel); d->completer->proxyModel = d->proxyModel; #endif @@ -2312,7 +2312,7 @@ void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel) d->proxyModel = 0; d->qFileDialogUi->listView->setModel(d->model); d->qFileDialogUi->treeView->setModel(d->model); -#ifndef QT_NO_COMPLETER +#ifndef QT_NO_FSCOMPLETER d->completer->setModel(d->model); d->completer->sourceModel = d->model; d->completer->proxyModel = 0; @@ -3218,7 +3218,7 @@ void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e) } } -#ifndef QT_NO_COMPLETER +#ifndef QT_NO_FSCOMPLETER QString QFSCompleter::pathFromIndex(const QModelIndex &index) const { diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm index 8e4c461..d9bec27 100644 --- a/src/gui/dialogs/qfiledialog_mac.mm +++ b/src/gui/dialogs/qfiledialog_mac.mm @@ -280,6 +280,10 @@ QT_USE_NAMESPACE - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { Q_UNUSED(sender); + + if ([filename length] == 0) + return NO; + QString qtFileName = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(filename); QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C))); QString path = info.absolutePath(); diff --git a/src/gui/dialogs/qfiledialog_p.h b/src/gui/dialogs/qfiledialog_p.h index 32cd397..0e447a3 100644 --- a/src/gui/dialogs/qfiledialog_p.h +++ b/src/gui/dialogs/qfiledialog_p.h @@ -234,9 +234,9 @@ public: QStringList watching; QFileSystemModel *model; -#ifndef QT_NO_COMPLETER +#ifndef QT_NO_FSCOMPLETER QFSCompleter *completer; -#endif //QT_NO_COMPLETER +#endif //QT_NO_FSCOMPLETER QFileDialog::FileMode fileMode; QFileDialog::AcceptMode acceptMode; diff --git a/src/gui/dialogs/qfscompleter_p.h b/src/gui/dialogs/qfscompleter_p.h index cb1b427..1edab2d 100644 --- a/src/gui/dialogs/qfscompleter_p.h +++ b/src/gui/dialogs/qfscompleter_p.h @@ -56,7 +56,7 @@ #include "qcompleter.h" #include <QtGui/qfilesystemmodel.h> QT_BEGIN_NAMESPACE -#ifndef QT_NO_COMPLETER +#ifndef QT_NO_FSCOMPLETER /*! QCompleter that can deal with QFileSystemModel @@ -76,7 +76,7 @@ public: QAbstractProxyModel *proxyModel; QFileSystemModel *sourceModel; }; -#endif // QT_NO_COMPLETER +#endif // QT_NO_FSCOMPLETER QT_END_NAMESPACE #endif // QFSCOMPLETOR_P_H diff --git a/src/gui/dialogs/qprintdialog_unix.cpp b/src/gui/dialogs/qprintdialog_unix.cpp index 7daa273..6fc270d 100644 --- a/src/gui/dialogs/qprintdialog_unix.cpp +++ b/src/gui/dialogs/qprintdialog_unix.cpp @@ -696,7 +696,7 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p) #ifndef QT_NO_FILESYSTEMMODEL QFileSystemModel *fsm = new QFileSystemModel(widget.filename); fsm->setRootPath(QDir::homePath()); -#if !defined(QT_NO_COMPLETER) && !defined(QT_NO_FILEDIALOG) +#if !defined(QT_NO_FSCOMPLETER) && !defined(QT_NO_FILEDIALOG) widget.filename->setCompleter(new QFSCompleter(fsm, widget.filename)); #endif #endif diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp index 843c4e2..51e83ac 100644 --- a/src/gui/dialogs/qprintdialog_win.cpp +++ b/src/gui/dialogs/qprintdialog_win.cpp @@ -139,7 +139,7 @@ static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWidget *parent, if (d->ep->printToFile) pd->Flags |= PD_PRINTTOFILE; Q_ASSERT(parent != 0 && parent->testAttribute(Qt::WA_WState_Created)); - pd->hwndOwner = parent->winId(); + pd->hwndOwner = parent->window()->winId(); pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage()); pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1; pd->nCopies = d->ep->num_copies; diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp index 0102e25..db1c9e9 100644 --- a/src/gui/dialogs/qwizard.cpp +++ b/src/gui/dialogs/qwizard.cpp @@ -1537,7 +1537,9 @@ void QWizardPrivate::handleAeroStyleChange() vistaHelper->backButton()->show(); } else { q->setMouseTracking(true); // ### original value possibly different +#ifndef QT_NO_CURSOR q->unsetCursor(); // ### ditto +#endif antiFlickerWidget->move(0, 0); vistaHelper->hideBackButton(); vistaHelper->setTitleBarIconAndCaptionVisible(true); diff --git a/src/gui/dialogs/qwizard_win.cpp b/src/gui/dialogs/qwizard_win.cpp index aa38ddc..f3f3a4e 100644 --- a/src/gui/dialogs/qwizard_win.cpp +++ b/src/gui/dialogs/qwizard_win.cpp @@ -387,10 +387,12 @@ bool QVistaHelper::winEvent(MSG* msg, long* result) void QVistaHelper::setMouseCursor(QPoint pos) { +#ifndef QT_NO_CURSOR if (rtTop.contains(pos)) wizard->setCursor(Qt::SizeVerCursor); else wizard->setCursor(Qt::ArrowCursor); +#endif } void QVistaHelper::mouseEvent(QEvent *event) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 91641b0..83f4f79 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -65,9 +65,6 @@ \o QGraphicsDropShadowEffect - renders a dropshadow behind the item \o QGraphicsColorizeEffect - renders the item in shades of any given color \o QGraphicsOpacityEffect - renders the item with an opacity - \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size - \o QGraphicsGrayscaleEffect - renders the item in shades of gray - \o QGraphicsBloomEffect - applies a blooming / glowing effect \endlist \img graphicseffect-effects.png @@ -100,9 +97,13 @@ */ #include "qgraphicseffect_p.h" +#include "private/qgraphicsitem_p.h" + +#include <QtGui/qgraphicsitem.h> #include <QtGui/qimage.h> #include <QtGui/qpainter.h> +#include <QtGui/qpaintengine.h> #include <QtCore/qrect.h> #include <QtCore/qdebug.h> #include <private/qdrawhelper_p.h> @@ -211,7 +212,23 @@ const QStyleOption *QGraphicsEffectSource::styleOption() const */ void QGraphicsEffectSource::draw(QPainter *painter) { - d_func()->draw(painter); + Q_D(const QGraphicsEffectSource); + + QPixmap pm; + if (QPixmapCache::find(d->m_cacheKey, &pm)) { + QTransform restoreTransform; + if (d->m_cachedSystem == Qt::DeviceCoordinates) { + restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + } + + painter->drawPixmap(d->m_cachedOffset, pm); + + if (d->m_cachedSystem == Qt::DeviceCoordinates) + painter->setWorldTransform(restoreTransform); + } else { + d_func()->draw(painter); + } } /*! @@ -251,9 +268,46 @@ bool QGraphicsEffectSource::isPixmap() const \sa QGraphicsEffect::draw(), boundingRect(), deviceRect() */ -QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset, PixmapPadMode mode) const { - return d_func()->pixmap(system, offset); + Q_D(const QGraphicsEffectSource); + + // Shortcut, no cache for childless pixmap items... + const QGraphicsItem *item = graphicsItem(); + if (system == Qt::LogicalCoordinates && mode == NoExpandPadMode && item && isPixmap()) { + return ((QGraphicsPixmapItem *) item)->pixmap(); + } + + if (system == Qt::DeviceCoordinates && item + && !static_cast<const QGraphicsItemEffectSourcePrivate *>(d_func())->info) { + qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context"); + return QPixmap(); + } + + QPixmap pm; + if (d->m_cachedSystem == system && d->m_cachedMode == mode) + QPixmapCache::find(d->m_cacheKey, &pm); + + if (pm.isNull()) { + pm = d->pixmap(system, &d->m_cachedOffset, mode); + d->m_cachedSystem = system; + d->m_cachedMode = mode; + + d->invalidateCache(); + d->m_cacheKey = QPixmapCache::insert(pm); + } + + if (offset) + *offset = d->m_cachedOffset; + + return pm; +} + +void QGraphicsEffectSourcePrivate::invalidateCache(bool effectRectChanged) const +{ + if (effectRectChanged && m_cachedMode != QGraphicsEffectSource::ExpandToEffectRectPadMode) + return; + QPixmapCache::remove(m_cacheKey); } /*! @@ -336,8 +390,10 @@ void QGraphicsEffect::setEnabled(bool enable) return; d->isEnabled = enable; - if (d->source) + if (d->source) { d->source->d_func()->effectBoundingRectChanged(); + d->source->d_func()->invalidateCache(); + } emit enabledChanged(enable); } @@ -391,8 +447,10 @@ QGraphicsEffectSource *QGraphicsEffect::source() const void QGraphicsEffect::updateBoundingRect() { Q_D(QGraphicsEffect); - if (d->source) + if (d->source) { d->source->d_func()->effectBoundingRectChanged(); + d->source->d_func()->invalidateCache(true); + } } /*! @@ -441,96 +499,6 @@ void QGraphicsEffect::sourceChanged(ChangeFlags flags) } /*! - \class QGraphicsGrayscaleEffect - \brief The QGraphicsGrayscaleEffect class provides a grayscale effect. - \since 4.6 - - A grayscale effect renders the source in shades of gray. - - \img graphicseffect-grayscale.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect -*/ - -/*! - Constructs a new QGraphicsGrayscale instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent) -{ -} - -/*! - Destroys the effect. -*/ -QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() -{ -} - - -/*! - \property QGraphicsGrayscaleEffect::strength - \brief the strength of the effect. - - By default, the strength is 1.0. - A strength 0.0 equals to no effect, while 1.0 means full grayscale. -*/ -qreal QGraphicsGrayscaleEffect::strength() const -{ - Q_D(const QGraphicsGrayscaleEffect); - return d->filter->strength(); -} - -void QGraphicsGrayscaleEffect::setStrength(qreal strength) -{ - Q_D(QGraphicsGrayscaleEffect); - if (qFuzzyCompare(d->filter->strength(), strength)) - return; - - d->filter->setStrength(strength); - d->opaque = !qFuzzyIsNull(strength); - update(); - emit strengthChanged(strength); -} - -/*! \fn void QGraphicsGrayscaleEffect::strengthChanged(qreal strength) - This signal is emitted whenever setStrength() changes the grayscale - strength property. \a strength contains the new strength value of - the grayscale effect. - */ - -/*! - \reimp -*/ -void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsGrayscaleEffect); - - if (!d->opaque) { - source->draw(painter); - return; - } - - QPoint offset; - if (source->isPixmap()) { - // No point in drawing in device coordinates (pixmap will be scaled anyways). - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - d->filter->draw(painter, offset, pixmap); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - d->filter->draw(painter, offset, pixmap); - painter->setWorldTransform(restoreTransform); - -} - -/*! \class QGraphicsColorizeEffect \brief The QGraphicsColorizeEffect class provides a colorize effect. \since 4.6 @@ -542,8 +510,7 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so \img graphicseffect-colorize.png - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsOpacityEffect + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsOpacityEffect */ /*! @@ -638,7 +605,8 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou QPoint offset; if (source->isPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset, + QGraphicsEffectSource::NoExpandPadMode); d->filter->draw(painter, offset, pixmap); return; } @@ -652,126 +620,6 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou } /*! - \class QGraphicsPixelizeEffect - \brief The QGraphicsPixelizeEffect class provides a pixelize effect. - \since 4.6 - - A pixelize effect renders the source in lower resolution. This effect is - useful for reducing details, like censorship. The resolution can be - modified using the setPixelSize() function. - - By default, the pixel size is 3. - - \img graphicseffect-pixelize.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect -*/ - -/*! - Constructs a new QGraphicsPixelizeEffect instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent) -{ -} - -/*! - Destroys the effect. -*/ -QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() -{ -} - -/*! - \property QGraphicsPixelizeEffect::pixelSize - \brief the size of a pixel in the effect. - - Setting the pixel size to 2 means two pixels in the source will be used to - represent one pixel. Using a bigger size results in lower resolution. - - By default, the pixel size is 3. -*/ -int QGraphicsPixelizeEffect::pixelSize() const -{ - Q_D(const QGraphicsPixelizeEffect); - return d->pixelSize; -} - -void QGraphicsPixelizeEffect::setPixelSize(int size) -{ - Q_D(QGraphicsPixelizeEffect); - if (d->pixelSize == size) - return; - - d->pixelSize = size; - update(); - emit pixelSizeChanged(size); -} - -/*! - \fn void QGraphicsPixelizeEffect::pixelSizeChanged(int size) - - This signal is emitted whenever the effect's pixel size changes. - The \a size parameter holds the effect's new pixel size. -*/ - -static inline void pixelize(QImage *image, int pixelSize) -{ - Q_ASSERT(pixelSize > 0); - Q_ASSERT(image); - int width = image->width(); - int height = image->height(); - for (int y = 0; y < height; y += pixelSize) { - int ys = qMin(height - 1, y + pixelSize / 2); - QRgb *sbuf = reinterpret_cast<QRgb*>(image->scanLine(ys)); - for (int x = 0; x < width; x += pixelSize) { - int xs = qMin(width - 1, x + pixelSize / 2); - QRgb color = sbuf[xs]; - for (int yi = 0; yi < qMin(pixelSize, height - y); ++yi) { - QRgb *buf = reinterpret_cast<QRgb*>(image->scanLine(y + yi)); - for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi) - buf[x + xi] = color; - } - } - } -} - -/*! - \reimp -*/ -void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsPixelizeEffect); - if (d->pixelSize <= 0) { - source->draw(painter); - return; - } - - QPoint offset; - if (source->isPixmap()) { - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - pixelize(&image, d->pixelSize); - painter->drawImage(offset, image); - return; - } - - // Draw pixmap in device coordinates to avoid pixmap scaling. - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - - // pixelize routine - QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - pixelize(&image, d->pixelSize); - - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); - painter->drawImage(offset, image); - painter->setWorldTransform(restoreTransform); -} - -/*! \class QGraphicsBlurEffect \brief The QGraphicsBlurEffect class provides a blur effect. \since 4.6 @@ -785,11 +633,30 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou \img graphicseffect-blur.png - \sa QGraphicsDropShadowEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect + \sa QGraphicsDropShadowEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ /*! + \enum QGraphicsBlurEffect::BlurHint + \since 4.6 + + This enum describes the possible hints that can be used to control how + blur effects are applied. The hints might not have an effect in all the + paint engines. + + \value QualityHint Indicates that rendering quality is the most important factor, + at the potential cost of lower performance. + + \value PerformanceHint Indicates that rendering performance is the most important factor, + at the potential cost of lower quality. + + \value AnimationHint Indicates that the blur radius is going to be animated, hinting + that the implementation can keep a cache of blurred verisons of the source pixmap. + Do not use this hint if the source item is going to be dynamically changing. +*/ + + +/*! Constructs a new QGraphicsBlurEffect instance. The \a parent parameter is passed to QGraphicsEffect's constructor. */ @@ -797,7 +664,7 @@ QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent) { Q_D(QGraphicsBlurEffect); - d->filter->setBlurHint(Qt::PerformanceHint); + d->filter->setBlurHint(QGraphicsBlurEffect::PerformanceHint); } /*! @@ -816,16 +683,16 @@ QGraphicsBlurEffect::~QGraphicsBlurEffect() By default, the blur radius is 5 pixels. */ -int QGraphicsBlurEffect::blurRadius() const +qreal QGraphicsBlurEffect::blurRadius() const { Q_D(const QGraphicsBlurEffect); return d->filter->radius(); } -void QGraphicsBlurEffect::setBlurRadius(int radius) +void QGraphicsBlurEffect::setBlurRadius(qreal radius) { Q_D(QGraphicsBlurEffect); - if (d->filter->radius() == radius) + if (qFuzzyCompare(d->filter->radius(), radius)) return; d->filter->setRadius(radius); @@ -834,7 +701,7 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) } /*! - \fn void QGraphicsBlurEffect::blurRadiusChanged(int radius) + \fn void QGraphicsBlurEffect::blurRadiusChanged(qreal radius) This signal is emitted whenever the effect's blur radius changes. The \a radius parameter holds the effect's new blur radius. @@ -844,20 +711,19 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) \property QGraphicsBlurEffect::blurHint \brief the blur hint of the effect. - Use the Qt::PerformanceHint hint to say that you want a faster blur, - and the Qt::QualityHint hint to say that you prefer a higher quality blur. - - When animating the blur radius it's recommended to use Qt::PerformanceHint. + Use the PerformanceHint hint to say that you want a faster blur, + the QualityHint hint to say that you prefer a higher quality blur, + or the AnimationHint when you want to animate the blur radius. - By default, the blur hint is Qt::PerformanceHint. + By default, the blur hint is PerformanceHint. */ -Qt::RenderHint QGraphicsBlurEffect::blurHint() const +QGraphicsBlurEffect::BlurHint QGraphicsBlurEffect::blurHint() const { Q_D(const QGraphicsBlurEffect); return d->filter->blurHint(); } -void QGraphicsBlurEffect::setBlurHint(Qt::RenderHint hint) +void QGraphicsBlurEffect::setBlurHint(QGraphicsBlurEffect::BlurHint hint) { Q_D(QGraphicsBlurEffect); if (d->filter->blurHint() == hint) @@ -868,7 +734,7 @@ void QGraphicsBlurEffect::setBlurHint(Qt::RenderHint hint) } /*! - \fn void QGraphicsBlurEffect::blurHintChanged(Qt::RenderHint hint) + \fn void QGraphicsBlurEffect::blurHintChanged(Qt::BlurHint hint) This signal is emitted whenever the effect's blur hint changes. The \a hint parameter holds the effect's new blur hint. @@ -894,9 +760,13 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) return; } + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToEffectRectPadMode; + if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) + mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode; + // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset, mode); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); @@ -920,8 +790,7 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) \img graphicseffect-drop-shadow.png - \sa QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, - QGraphicsColorizeEffect, QGraphicsOpacityEffect + \sa QGraphicsBlurEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ /*! @@ -971,6 +840,8 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) By default, the horizontal shadow offset is 8 pixels. + + \sa yOffset(), offset() */ @@ -1001,16 +872,16 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) \sa color(), offset(). */ -int QGraphicsDropShadowEffect::blurRadius() const +qreal QGraphicsDropShadowEffect::blurRadius() const { Q_D(const QGraphicsDropShadowEffect); return d->filter->blurRadius(); } -void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) +void QGraphicsDropShadowEffect::setBlurRadius(qreal blurRadius) { Q_D(QGraphicsDropShadowEffect); - if (d->filter->blurRadius() == blurRadius) + if (qFuzzyCompare(d->filter->blurRadius(), blurRadius)) return; d->filter->setBlurRadius(blurRadius); @@ -1019,7 +890,7 @@ void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) } /*! - \fn void QGraphicsDropShadowEffect::blurRadiusChanged(int blurRadius) + \fn void QGraphicsDropShadowEffect::blurRadiusChanged(qreal blurRadius) This signal is emitted whenever the effect's blur radius changes. The \a blurRadius parameter holds the effect's new blur radius. @@ -1078,9 +949,13 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s return; } + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToEffectRectPadMode; + if (painter->paintEngine()->type() == QPaintEngine::OpenGL2) + mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode; + // Draw pixmap in device coordinates to avoid pixmap scaling. QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset, mode); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap); @@ -1100,8 +975,7 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s \img graphicseffect-opacity.png - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsColorizeEffect + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsColorizeEffect */ /*! @@ -1218,295 +1092,39 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour return; } - painter->save(); - painter->setOpacity(d->opacity); QPoint offset; - if (source->isPixmap()) { - // No point in drawing in device coordinates (pixmap will be scaled anyways). - if (!d->hasOpacityMask) { - const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); - painter->drawPixmap(offset, pixmap); - } else { - QRect srcBrect = source->boundingRect().toAlignedRect(); - offset = srcBrect.topLeft(); - QPixmap pixmap(srcBrect.size()); - pixmap.fill(Qt::transparent); - - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(painter->renderHints()); - pixmapPainter.translate(-offset); - source->draw(&pixmapPainter); - pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - pixmapPainter.fillRect(srcBrect, d->opacityMask); - pixmapPainter.end(); - - painter->drawPixmap(offset, pixmap); - } - } else { - // Draw pixmap in device coordinates to avoid pixmap scaling; - if (!d->hasOpacityMask) { - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); - painter->setWorldTransform(QTransform()); - painter->drawPixmap(offset, pixmap); - } else { - QTransform worldTransform = painter->worldTransform(); - - // Calculate source bounding rect in logical and device coordinates. - QRectF srcBrect = source->boundingRect(); - QRect srcDeviceBrect = worldTransform.mapRect(srcBrect).toAlignedRect(); - srcDeviceBrect &= source->deviceRect(); + Qt::CoordinateSystem system = source->isPixmap() ? Qt::LogicalCoordinates : Qt::DeviceCoordinates; + QPixmap pixmap = source->pixmap(system, &offset, QGraphicsEffectSource::NoExpandPadMode); + if (pixmap.isNull()) + return; - offset = srcDeviceBrect.topLeft(); - worldTransform *= QTransform::fromTranslate(-srcDeviceBrect.x(), -srcDeviceBrect.y()); - QPixmap pixmap(srcDeviceBrect.size()); - pixmap.fill(Qt::transparent); + painter->save(); + painter->setOpacity(d->opacity); - QPainter pixmapPainter(&pixmap); - pixmapPainter.setRenderHints(painter->renderHints()); + if (d->hasOpacityMask) { + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(painter->renderHints()); + pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + if (system == Qt::DeviceCoordinates) { + QTransform worldTransform = painter->worldTransform(); + worldTransform *= QTransform::fromTranslate(-offset.x(), -offset.y()); pixmapPainter.setWorldTransform(worldTransform); - source->draw(&pixmapPainter); - pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - pixmapPainter.fillRect(srcBrect, d->opacityMask); - pixmapPainter.end(); - - painter->setWorldTransform(QTransform()); - painter->drawPixmap(offset, pixmap); + pixmapPainter.fillRect(source->boundingRect(), d->opacityMask); + } else { + pixmapPainter.translate(-offset); + pixmapPainter.fillRect(pixmap.rect(), d->opacityMask); } } - painter->restore(); -} - -/*! - \class QGraphicsBloomEffect - \brief The QGraphicsBloomEffect class provides a bloom/glow effect. - \since 4.6 - - A bloom/glow effect adds fringes of light around bright areas in the source. + if (system == Qt::DeviceCoordinates) + painter->setWorldTransform(QTransform()); - \img graphicseffect-bloom.png - - \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, - QGraphicsGrayscaleEffect, QGraphicsColorizeEffect -*/ - -/*! - Constructs a new QGraphicsBloomEffect instance. - The \a parent parameter is passed to QGraphicsEffect's constructor. -*/ -QGraphicsBloomEffect::QGraphicsBloomEffect(QObject *parent) - : QGraphicsEffect(*new QGraphicsBloomEffectPrivate, parent) -{ - Q_D(QGraphicsBloomEffect); - for (int i = 0; i < 256; ++i) - d->colorTable[i] = qMin(i + d->brightness, 255); -} - -/*! - Destroys the effect. -*/ -QGraphicsBloomEffect::~QGraphicsBloomEffect() -{ -} - -/*! - \reimp -*/ -QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QGraphicsBloomEffect); - const qreal delta = d->blurFilter.radius() * 2; - return rect.adjusted(-delta, -delta, delta, delta); -} - -/*! - \property QGraphicsBloomEffect::blurRadius - \brief the blur radius in pixels of the effect. - - Using a smaller radius results in a sharper appearance, whereas a bigger - radius results in a more blurred appearance. - - By default, the blur radius is 5 pixels. - - \sa strength(), brightness() -*/ -int QGraphicsBloomEffect::blurRadius() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurFilter.radius(); -} - -void QGraphicsBloomEffect::setBlurRadius(int radius) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurFilter.radius() == radius) - return; - - d->blurFilter.setRadius(radius); - updateBoundingRect(); - emit blurRadiusChanged(radius); -} - -/*! - \fn void QGraphicsBloomEffect::blurRadiusChanged(int blurRadius) - - This signal is emitted whenever the effect's blur radius changes. - The \a blurRadius parameter holds the effect's new blur radius. -*/ - -/*! - \property QGraphicsBloomEffect::blurHint - \brief the blur hint of the effect. - - Use the Qt::PerformanceHint hint to say that you want a faster blur, - and the Qt::QualityHint hint to say that you prefer a higher quality blur. - - When animating the blur radius it's recommended to use Qt::PerformanceHint. - - By default, the blur hint is Qt::PerformanceHint. -*/ -Qt::RenderHint QGraphicsBloomEffect::blurHint() const -{ - Q_D(const QGraphicsBloomEffect); - return d->blurFilter.blurHint(); -} - -void QGraphicsBloomEffect::setBlurHint(Qt::RenderHint hint) -{ - Q_D(QGraphicsBloomEffect); - if (d->blurFilter.blurHint() == hint) - return; - - d->blurFilter.setBlurHint(hint); - emit blurHintChanged(hint); -} - -/*! - \fn void QGraphicsBloomEffect::blurHintChanged(Qt::RenderHint hint) - - This signal is emitted whenever the effect's blur hint changes. - The \a hint parameter holds the effect's new blur hint. -*/ - -/*! - \property QGraphicsBloomEffect::brightness - \brief the brightness of the glow. - - The value should be in the range of 0 to 255, where 0 is dark - and 255 is bright. - - By default, the brightness is 70. - - \sa strength(), blurRadius() -*/ -int QGraphicsBloomEffect::brightness() const -{ - Q_D(const QGraphicsBloomEffect); - return d->brightness; -} - -void QGraphicsBloomEffect::setBrightness(int brightness) -{ - Q_D(QGraphicsBloomEffect); - brightness = qBound(0, brightness, 255); - if (d->brightness == brightness) - return; - - d->brightness = brightness; - for (int i = 0; i < 256; ++i) - d->colorTable[i] = qMin(i + brightness, 255); - - update(); - emit brightnessChanged(brightness); -} - -/*! - \fn void QGraphicsBloomEffect::brightnessChanged(int brightness) - - This signal is emitted whenever the effect's brightness changes. - The \a brightness parameter holds the effect's new brightness. -*/ - -/*! - \property QGraphicsBloomEffect::strength - \brief the strength of the effect. - - A strength 0.0 equals to no effect, while 1.0 means maximum glow. - - By default, the strength is 0.7. -*/ -qreal QGraphicsBloomEffect::strength() const -{ - Q_D(const QGraphicsBloomEffect); - return d->strength; -} - -void QGraphicsBloomEffect::setStrength(qreal strength) -{ - Q_D(QGraphicsBloomEffect); - strength = qBound(qreal(0.0), strength, qreal(1.0)); - if (qFuzzyCompare(d->strength, strength)) - return; - - d->strength = strength; - update(); - emit strengthChanged(strength); -} - -/*! - \fn void QGraphicsBloomEffect::strengthChanged(qreal strength) - - This signal is emitted whenever the effect's strength changes. - The \a strength parameter holds the effect's new strength. -*/ - -extern QPixmap qt_toRasterPixmap(const QPixmap &pixmap); - -/*! - \reimp -*/ -void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) -{ - Q_D(QGraphicsBloomEffect); - if (d->strength < 0.001) { - source->draw(painter); - return; - } - - QPoint offset; - QPixmap pixmap = qt_toRasterPixmap(source->pixmap(Qt::DeviceCoordinates, &offset)); - - // Blur. - QImage overlay(pixmap.size(), QImage::Format_ARGB32_Premultiplied); - overlay.fill(0); - - QPainter blurPainter(&overlay); - d->blurFilter.draw(&blurPainter, QPointF(), pixmap); - blurPainter.end(); - - // Brighten. - const int numBits = overlay.width() * overlay.height(); - QRgb *bits = reinterpret_cast<QRgb *>(overlay.bits()); - for (int i = 0; i < numBits; ++i) { - const QRgb pixel = INV_PREMUL(bits[i]); - bits[i] = PREMUL(qRgba(d->colorTable[qRed(pixel)], d->colorTable[qGreen(pixel)], - d->colorTable[qBlue(pixel)], qAlpha(pixel))); - } - - // Composite. - QPainter compPainter(&pixmap); - compPainter.setCompositionMode(QPainter::CompositionMode_Overlay); - compPainter.setOpacity(d->strength); - compPainter.drawImage(0, 0, overlay); - compPainter.end(); - - QTransform restoreTransform = painter->worldTransform(); - painter->setWorldTransform(QTransform()); painter->drawPixmap(offset, pixmap); - painter->setWorldTransform(restoreTransform); + painter->restore(); } + QT_END_NAMESPACE diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index c5d3ede..7335a25 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -64,6 +64,12 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject { Q_OBJECT public: + enum PixmapPadMode { + NoExpandPadMode, + ExpandToTransparentBorderPadMode, + ExpandToEffectRectPadMode + }; + ~QGraphicsEffectSource(); const QGraphicsItem *graphicsItem() const; const QWidget *widget() const; @@ -75,7 +81,9 @@ public: QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; QRect deviceRect() const; - QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; + QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, + QPoint *offset = 0, + PixmapPadMode mode = ExpandToEffectRectPadMode) const; protected: QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); @@ -87,6 +95,7 @@ private: friend class QGraphicsEffectPrivate; friend class QGraphicsScenePrivate; friend class QGraphicsItem; + friend class QGraphicsItemPrivate; friend class QWidget; friend class QWidgetPrivate; }; @@ -140,31 +149,6 @@ private: }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsEffect::ChangeFlags) -class QGraphicsGrayscaleEffectPrivate; -class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) -public: - QGraphicsGrayscaleEffect(QObject *parent = 0); - ~QGraphicsGrayscaleEffect(); - - qreal strength() const; - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -public Q_SLOTS: - void setStrength(qreal strength); - -Q_SIGNALS: - void strengthChanged(qreal strength); - -private: - Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) - Q_DISABLE_COPY(QGraphicsGrayscaleEffect) -}; - class QGraphicsColorizeEffectPrivate; class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { @@ -194,52 +178,33 @@ private: Q_DISABLE_COPY(QGraphicsColorizeEffect) }; -class QGraphicsPixelizeEffectPrivate; -class Q_GUI_EXPORT QGraphicsPixelizeEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize NOTIFY pixelSizeChanged) -public: - QGraphicsPixelizeEffect(QObject *parent = 0); - ~QGraphicsPixelizeEffect(); - - int pixelSize() const; - -public Q_SLOTS: - void setPixelSize(int pixelSize); - -Q_SIGNALS: - void pixelSizeChanged(int pixelSize); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect) - Q_DISABLE_COPY(QGraphicsPixelizeEffect) -}; - class QGraphicsBlurEffectPrivate; class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) - Q_PROPERTY(Qt::RenderHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) + Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(BlurHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) public: + enum BlurHint { + QualityHint, + PerformanceHint, + AnimationHint + }; + QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); QRectF boundingRectFor(const QRectF &rect) const; - int blurRadius() const; - Qt::RenderHint blurHint() const; + qreal blurRadius() const; + BlurHint blurHint() const; public Q_SLOTS: - void setBlurRadius(int blurRadius); - void setBlurHint(Qt::RenderHint hint); + void setBlurRadius(qreal blurRadius); + void setBlurHint(BlurHint hint); Q_SIGNALS: - void blurRadiusChanged(int blurRadius); - void blurHintChanged(Qt::RenderHint hint); + void blurRadiusChanged(qreal blurRadius); + void blurHintChanged(BlurHint hint); protected: void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -256,7 +221,7 @@ class Q_GUI_EXPORT QGraphicsDropShadowEffect: public QGraphicsEffect Q_PROPERTY(QPointF offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(qreal xOffset READ xOffset WRITE setXOffset NOTIFY offsetChanged) Q_PROPERTY(qreal yOffset READ yOffset WRITE setYOffset NOTIFY offsetChanged) - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(qreal blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) public: QGraphicsDropShadowEffect(QObject *parent = 0); @@ -271,7 +236,7 @@ public: inline qreal yOffset() const { return offset().y(); } - int blurRadius() const; + qreal blurRadius() const; QColor color() const; public Q_SLOTS: @@ -289,12 +254,12 @@ public Q_SLOTS: inline void setYOffset(qreal dy) { setOffset(QPointF(xOffset(), dy)); } - void setBlurRadius(int blurRadius); + void setBlurRadius(qreal blurRadius); void setColor(const QColor &color); Q_SIGNALS: void offsetChanged(const QPointF &offset); - void blurRadiusChanged(int blurRadius); + void blurRadiusChanged(qreal blurRadius); void colorChanged(const QColor &color); protected: @@ -334,44 +299,6 @@ private: Q_DISABLE_COPY(QGraphicsOpacityEffect) }; -class QGraphicsBloomEffectPrivate; -class Q_GUI_EXPORT QGraphicsBloomEffect: public QGraphicsEffect -{ - Q_OBJECT - Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) - Q_PROPERTY(Qt::RenderHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) - Q_PROPERTY(int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged) - Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) -public: - QGraphicsBloomEffect(QObject *parent = 0); - ~QGraphicsBloomEffect(); - - QRectF boundingRectFor(const QRectF &rect) const; - int blurRadius() const; - Qt::RenderHint blurHint() const; - int brightness() const; - qreal strength() const; - -public Q_SLOTS: - void setBlurRadius(int blurRadius); - void setBlurHint(Qt::RenderHint hint); - void setBrightness(int brightness); - void setStrength(qreal strength); - -Q_SIGNALS: - void blurRadiusChanged(int blurRadius); - void blurHintChanged(Qt::RenderHint hint); - void brightnessChanged(int brightness); - void strengthChanged(qreal strength); - -protected: - void draw(QPainter *painter, QGraphicsEffectSource *source); - -private: - Q_DECLARE_PRIVATE(QGraphicsBloomEffect) - Q_DISABLE_COPY(QGraphicsBloomEffect) -}; - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index ff2fb85..0ff5794 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -55,6 +55,8 @@ #include "qgraphicseffect.h" +#include <QPixmapCache> + #include <private/qobject_p.h> #include <private/qpixmapfilter_p.h> @@ -64,8 +66,13 @@ class QGraphicsEffectSourcePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffectSource) public: - QGraphicsEffectSourcePrivate() : QObjectPrivate() {} - virtual ~QGraphicsEffectSourcePrivate() {} + QGraphicsEffectSourcePrivate() + : QObjectPrivate() + , m_cachedSystem(Qt::DeviceCoordinates) + , m_cachedMode(QGraphicsEffectSource::ExpandToTransparentBorderPadMode) + {} + + virtual ~QGraphicsEffectSourcePrivate() { invalidateCache(); } virtual void detach() = 0; virtual QRectF boundingRect(Qt::CoordinateSystem system) const = 0; virtual QRect deviceRect() const = 0; @@ -75,11 +82,20 @@ public: virtual void draw(QPainter *p) = 0; virtual void update() = 0; virtual bool isPixmap() const = 0; - virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0; + virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0, + QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode) const = 0; virtual void effectBoundingRectChanged() = 0; + void invalidateCache(bool effectRectChanged = false) const; + friend class QGraphicsScenePrivate; friend class QGraphicsItem; friend class QGraphicsItemPrivate; + +private: + mutable Qt::CoordinateSystem m_cachedSystem; + mutable QGraphicsEffectSource::PixmapPadMode m_cachedMode; + mutable QPoint m_cachedOffset; + mutable QPixmapCache::Key m_cacheKey; }; class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate @@ -93,6 +109,7 @@ public: QGraphicsEffect::ChangeFlags flags; if (source) { flags |= QGraphicsEffect::SourceDetached; + source->d_func()->invalidateCache(); source->d_func()->detach(); delete source; } @@ -108,22 +125,6 @@ public: quint32 padding : 31; // feel free to use }; -class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) -public: - QGraphicsGrayscaleEffectPrivate() - : opaque(true) - { - filter = new QPixmapColorizeFilter; - filter->setColor(Qt::black); - } - ~QGraphicsGrayscaleEffectPrivate() { delete filter; } - - QPixmapColorizeFilter *filter; - quint32 opaque : 1; - quint32 padding : 31; -}; class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate { @@ -141,15 +142,6 @@ public: quint32 padding : 31; }; -class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPixelizeEffect) -public: - QGraphicsPixelizeEffectPrivate() : pixelSize(3) {} - - int pixelSize; -}; - class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsBlurEffect) @@ -185,18 +177,6 @@ public: uint hasOpacityMask : 1; }; -class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsBlurEffect) -public: - QGraphicsBloomEffectPrivate() : brightness(70), strength(qreal(0.7)) {} - - QPixmapBlurFilter blurFilter; - int colorTable[256]; - int brightness; - qreal strength; -}; - QT_END_NAMESPACE #endif // QGRAPHICSEFFECT_P_H diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri index ba991bd..627d511 100644 --- a/src/gui/egl/egl.pri +++ b/src/gui/egl/egl.pri @@ -6,7 +6,7 @@ SOURCES += \ egl/qegl.cpp \ egl/qeglproperties.cpp -contains(QT_CONFIG, wince*): SOURCES += egl/qegl_wince.cpp +wince*: SOURCES += egl/qegl_wince.cpp unix { embedded { diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp index c61e1d3..2d37edb 100644 --- a/src/gui/egl/qeglproperties.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -88,8 +88,12 @@ int QEglProperties::value(int name) const #if defined(EGL_ALPHA_MASK_SIZE) case EGL_ALPHA_MASK_SIZE: return 0; #endif +#if defined(EGL_BIND_TO_TEXTURE_RGB) case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE; +#endif +#if defined(EGL_BIND_TO_TEXTURE_RGBA) case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE; +#endif #if defined(EGL_COLOR_BUFFER_TYPE) case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER; #endif diff --git a/src/gui/embedded/qdecorationdefault_qws.cpp b/src/gui/embedded/qdecorationdefault_qws.cpp index 5bc8826..70389d3 100644 --- a/src/gui/embedded/qdecorationdefault_qws.cpp +++ b/src/gui/embedded/qdecorationdefault_qws.cpp @@ -394,7 +394,7 @@ QPixmap QDecorationDefault::pixmapFor(const QWidget *widget, */ int QDecorationDefault::titleBarHeight(const QWidget *) { - return qMax(20, QApplication::fontMetrics().lineSpacing() + BORDER_WIDTH); + return qMax(20, QApplication::fontMetrics().height() + BORDER_WIDTH); } /*! diff --git a/src/gui/embedded/qdecorationwindows_qws.cpp b/src/gui/embedded/qdecorationwindows_qws.cpp index 77393cf..7764ca5 100644 --- a/src/gui/embedded/qdecorationwindows_qws.cpp +++ b/src/gui/embedded/qdecorationwindows_qws.cpp @@ -216,7 +216,7 @@ QRegion QDecorationWindows::region(const QWidget *widget, const QRect &rect, int bool hasMinimize = flags & Qt::WindowMinimizeButtonHint; bool hasMaximize = flags & Qt::WindowMaximizeButtonHint; const QFontMetrics fontMetrics = QApplication::fontMetrics(); - int titleHeight = hasTitle ? qMax(20, fontMetrics.lineSpacing()) : 0; + int titleHeight = hasTitle ? qMax(20, fontMetrics.height()) : 0; int state = widget->windowState(); bool isMinimized = state & Qt::WindowMinimized; bool isMaximized = state & Qt::WindowMaximized; diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index c39e8a6..56d70e1 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -48,36 +48,60 @@ \ingroup geomanagement \ingroup graphicsview-api - The anchor layout is a layout where one can specify how widgets should be placed relative to - each other. The specification is called an anchor, and it is set up by calling anchor(). + The anchor layout allows developers to specify how widgets should be placed relative to + each other, and to the layout itself. The specification is made by adding anchors to the + layout by calling addAnchor(), addAnchors() or addCornerAnchors(). + + Existing anchors in the layout can be accessed with the anchor() function. + Items that are anchored are automatically added to the layout, and if items + are removed, all their anchors will be automatically removed. + + \beginfloatleft + \inlineimage simpleanchorlayout-example.png Using an anchor layout to align simple colored widgets. + \endfloat + Anchors are always set up between edges of an item, where the "center" is also considered to - be an edge. Considering this example: - \code - QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; - QGraphicsWidget *a = new QGraphicsWidget; - QGraphicsWidget *b = new QGraphicsWidget; - l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); - \endcode - - Here is the right edge of item A anchored to the left edge of item B, with the result that - item B will be placed to the right of item A, with a spacing between A and B. If the - spacing is negative, the items will overlap to some extent. Items that are anchored are - automatically added to the layout, and if items are removed, all their anchors will be - automatically removed - - \section1 Size Hints and Size Policies in QGraphicsAnchorLayout + be an edge. Consider the following example: + + \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors + + Here, the right edge of item \c a is anchored to the left edge of item \c b and the bottom + edge of item \c a is anchored to the top edge of item \c b, with the result that + item \c b will be placed diagonally to the right and below item \c b. + + The addCornerAnchors() function provides a simpler way of anchoring the corners + of two widgets than the two individual calls to addAnchor() shown in the code + above. Here, we see how a widget can be anchored to the top-left corner of the enclosing + layout: + + \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor + + In cases where anchors are used to match the widths or heights of widgets, it is + convenient to use the addAnchors() function. As with the other functions for specifying + anchors, it can also be used to anchor a widget to a layout. + + \clearfloat + \section1 Size Hints and Size Policies in an Anchor Layout QGraphicsAnchorLayout respects each item's size hints and size policies. However it does - not respect stretch factors currently. This might change in the future, so please refrain - from using stretch factors in anchor layout to avoid any future regressions. + not currently respect their stretch factors. This might change in the future, so avoid + using stretch factors in anchor layouts if you want to avoid any future regressions in + behavior. + + \section1 Spacing within an Anchor Layout + + The layout may distribute some space between the items. If the spacing has not been + explicitly specified, the actual amount of space will usually be 0. + + However, if the first edge is the \e opposite of the second edge (e.g., the right edge + of the first widget is anchored to the left edge of the second widget), the size of the + anchor will be queried from the style through a pixel metric: + \l{QStyle::}{PM_LayoutHorizontalSpacing} for horizontal anchors and + \l{QStyle::}{PM_LayoutVerticalSpacing} for vertical anchors. - \section1 Spacing within QGraphicsAnchorLayout + If the spacing is negative, the items will overlap to some extent. - Between the items, the layout can distribute some space. If the spacing has not been - explicitly specified, the actual amount of space will usually be 0, but if the first edge - is the "opposite" of the second edge (i.e. Right is anchored to Left or vice-versa), the - size of the anchor will be queried from the style through the pixelMetric - PM_LayoutHorizontalSpacing (or PM_LayoutVerticalSpacing for vertical anchors). + \sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout */ /*! @@ -99,7 +123,7 @@ */ #include "qgraphicsanchorlayout_p.h" - +#ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE QGraphicsAnchor::QGraphicsAnchor(QGraphicsAnchorLayout *parentLayout) @@ -118,16 +142,26 @@ QGraphicsAnchor::~QGraphicsAnchor() } /*! - Sets the size policy of the anchor to \a policy. + \property QGraphicsAnchor::sizePolicy + \brief the size policy for the QGraphicsAnchor. + + By setting the size policy on an anchor you can configure how the item can resize itself + from its preferred spacing. For instance, if the anchor has the size policy + QSizePolicy::Minimum, the spacing is the minimum size of the anchor. However, its size + can grow up to the anchors maximum size. If the default size policy is QSizePolicy::Fixed, + the anchor can neither grow or shrink, which means that the only size the anchor can have + is the spacing. QSizePolicy::Fixed is the default size policy. + QGraphicsAnchor always has a minimum spacing of 0 and a very large maximum spacing. + + \sa QGraphicsAnchor::spacing */ + void QGraphicsAnchor::setSizePolicy(QSizePolicy::Policy policy) { Q_D(QGraphicsAnchor); d->setSizePolicy(policy); } -/*! - Returns the size policy of the anchor. The default size policy is QSizePolicy::Fixed -*/ + QSizePolicy::Policy QGraphicsAnchor::sizePolicy() const { Q_D(const QGraphicsAnchor); @@ -136,12 +170,12 @@ QSizePolicy::Policy QGraphicsAnchor::sizePolicy() const /*! \property QGraphicsAnchor::spacing - \brief the space between items in the QGraphicsAnchorLayout. + \brief the preferred space between items in the QGraphicsAnchorLayout. Depending on the anchor type, the default spacing is either 0 or a value returned from the style. - \sa QGraphicsAnchorLayout::anchor() + \sa QGraphicsAnchorLayout::addAnchor() */ void QGraphicsAnchor::setSpacing(qreal spacing) { @@ -205,7 +239,7 @@ QGraphicsAnchorLayout::~QGraphicsAnchorLayout() If there is already an anchor between the edges, the the new anchor will replace the old one. \a firstItem and \a secondItem are automatically added to the layout if they are not part - of the layout. This means that count() can increase with up to 2. + of the layout. This means that count() can increase by up to 2. The spacing an anchor will get depends on the type of anchor. For instance, anchors from the Right edge of one item to the Left edge of another (or vice versa) will use the default @@ -215,7 +249,10 @@ QGraphicsAnchorLayout::~QGraphicsAnchorLayout() The spacing can also be set manually by using QGraphicsAnchor::setSpacing() method. - \sa addCornerAnchors(), addAnchors() + Calling this function where \a firstItem or \a secondItem are ancestors of the layout have + undefined behaviour. + + \sa addAnchors(), addCornerAnchors() */ QGraphicsAnchor * QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, @@ -240,29 +277,26 @@ QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint fi } /*! - Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal - edge and another one for the vertical edge that the corners \a firstCorner and \a - secondCorner specifies. - The magnitude of the anchors is picked up from the style. + Creates two anchors between \a firstItem and \a secondItem specified by the corners, + \a firstCorner and \a secondCorner, where one is for the horizontal edge and another + one for the vertical edge. + + This is a convenience function, since anchoring corners can be expressed as anchoring + two edges. For instance: - This is a convenience function, since anchoring corners can be expressed as anchoring two edges. - For instance, - \code - layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop); - layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft); - \endcode + \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor in two steps - has the same effect as + This can also be achieved with the following line of code: - \code - layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft); - \endcode + \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor If there is already an anchor between the edge pairs, it will be replaced by the anchors that this function specifies. \a firstItem and \a secondItem are automatically added to the layout if they are not part of the - layout. This means that count() can increase with up to 2. + layout. This means that count() can increase by up to 2. + + \sa addAnchor(), addAnchors() */ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, Qt::Corner firstCorner, @@ -289,17 +323,16 @@ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, edges of \a secondItem, so that \a firstItem has the same size as \a secondItem in the dimensions specified by \a orientations. - Calling this convenience function with the following arguments - \code - l->addAnchors(firstItem, secondItem, Qt::Horizontal) - \endcode + For example, the following example anchors the left and right edges of two items + to match their widths: + + \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes in two steps + + This can also be achieved using the following line of code: - is the same as + \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes - \code - l->addAnchor(firstItem, Qt::AnchorLeft, secondItem, Qt::AnchorLeft); - l->addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); - \endcode + \sa addAnchor(), addCornerAnchors() */ void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem, QGraphicsLayoutItem *secondItem, @@ -387,7 +420,7 @@ void QGraphicsAnchorLayout::setSpacing(qreal spacing) qreal QGraphicsAnchorLayout::horizontalSpacing() const { Q_D(const QGraphicsAnchorLayout); - return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Horizontal); + return d->styleInfo().defaultSpacing(Qt::Horizontal); } /*! @@ -398,7 +431,7 @@ qreal QGraphicsAnchorLayout::horizontalSpacing() const qreal QGraphicsAnchorLayout::verticalSpacing() const { Q_D(const QGraphicsAnchorLayout); - return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Vertical); + return d->styleInfo().defaultSpacing(Qt::Vertical); } /*! @@ -468,7 +501,8 @@ void QGraphicsAnchorLayout::invalidate() { Q_D(QGraphicsAnchorLayout); QGraphicsLayout::invalidate(); - d->calculateGraphCacheDirty = 1; + d->calculateGraphCacheDirty = true; + d->styleInfoDirty = true; } /*! @@ -502,3 +536,4 @@ QSizeF QGraphicsAnchorLayout::sizeHint(Qt::SizeHint which, const QSizeF &constra } QT_END_NAMESPACE +#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h index f09ac43..01c3a86 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout.h @@ -62,12 +62,13 @@ class Q_GUI_EXPORT QGraphicsAnchor : public QObject { Q_OBJECT Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing RESET unsetSpacing) + Q_PROPERTY(QSizePolicy::Policy sizePolicy READ sizePolicy WRITE setSizePolicy) public: void setSpacing(qreal spacing); void unsetSpacing(); + qreal spacing() const; void setSizePolicy(QSizePolicy::Policy policy); QSizePolicy::Policy sizePolicy() const; - qreal spacing() const; ~QGraphicsAnchor(); private: QGraphicsAnchor(QGraphicsAnchorLayout *parent); diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 8c8c303..41aa8aa 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <QtGui/qwidget.h> +#include <QtGui/qapplication.h> #include <QtCore/qlinkedlist.h> #include <QtCore/qstack.h> @@ -48,7 +49,7 @@ #endif #include "qgraphicsanchorlayout_p.h" - +#ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE @@ -141,34 +142,25 @@ static void internalSizeHints(QSizePolicy::Policy policy, *expSize = *prefSize; } -void AnchorData::refreshSizeHints(qreal effectiveSpacing) +bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) { - const bool isInternalAnchor = from->m_item == to->m_item; - QSizePolicy::Policy policy; qreal minSizeHint; qreal prefSizeHint; qreal maxSizeHint; - if (isInternalAnchor) { - const QGraphicsAnchorLayoutPrivate::Orientation orient = - QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge); - const Qt::AnchorPoint centerEdge = - QGraphicsAnchorLayoutPrivate::pickEdge(Qt::AnchorHorizontalCenter, orient); - bool hasCenter = (from->m_edge == centerEdge || to->m_edge == centerEdge); - + // It is an internal anchor + if (item) { if (isLayoutAnchor) { minSize = 0; prefSize = 0; expSize = 0; maxSize = QWIDGETSIZE_MAX; - if (hasCenter) + if (isCenterAnchor) maxSize /= 2; - return; + return true; } else { - - QGraphicsLayoutItem *item = from->m_item; - if (orient == QGraphicsAnchorLayoutPrivate::Horizontal) { + if (orientation == QGraphicsAnchorLayoutPrivate::Horizontal) { policy = item->sizePolicy().horizontalPolicy(); minSizeHint = item->effectiveSizeHint(Qt::MinimumSize).width(); prefSizeHint = item->effectiveSizeHint(Qt::PreferredSize).width(); @@ -180,7 +172,7 @@ void AnchorData::refreshSizeHints(qreal effectiveSpacing) maxSizeHint = item->effectiveSizeHint(Qt::MaximumSize).height(); } - if (hasCenter) { + if (isCenterAnchor) { minSizeHint /= 2; prefSizeHint /= 2; maxSizeHint /= 2; @@ -196,7 +188,20 @@ void AnchorData::refreshSizeHints(qreal effectiveSpacing) // their effective size hints might be narrowed down due to their size policies. prefSizeHint = prefSize; } else { - prefSizeHint = effectiveSpacing; + const Qt::Orientation orient = Qt::Orientation(QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge) + 1); + qreal s = styleInfo->defaultSpacing(orient); + if (s < 0) { + QSizePolicy::ControlType controlTypeFrom = from->m_item->sizePolicy().controlType(); + QSizePolicy::ControlType controlTypeTo = to->m_item->sizePolicy().controlType(); + s = styleInfo->perItemSpacing(controlTypeFrom, controlTypeTo, orient); + + // ### Currently we do not support negative anchors inside the graph. + // To avoid those being created by a negative style spacing, we must + // make this test. + if (s < 0) + s = 0; + } + prefSizeHint = s; } maxSizeHint = QWIDGETSIZE_MAX; } @@ -214,6 +219,8 @@ void AnchorData::refreshSizeHints(qreal effectiveSpacing) sizeAtPreferred = prefSize; sizeAtExpanding = prefSize; sizeAtMaximum = prefSize; + + return true; } void ParallelAnchorData::updateChildrenSizes() @@ -227,26 +234,29 @@ void ParallelAnchorData::updateChildrenSizes() secondEdge->updateChildrenSizes(); } -void ParallelAnchorData::refreshSizeHints(qreal effectiveSpacing) +bool ParallelAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) { - refreshSizeHints_helper(effectiveSpacing); + return refreshSizeHints_helper(styleInfo); } -void ParallelAnchorData::refreshSizeHints_helper(qreal effectiveSpacing, +bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren) { - if (refreshChildren) { - firstEdge->refreshSizeHints(effectiveSpacing); - secondEdge->refreshSizeHints(effectiveSpacing); + if (refreshChildren && (!firstEdge->refreshSizeHints(styleInfo) + || !secondEdge->refreshSizeHints(styleInfo))) { + return false; } - // ### should we warn if the parallel connection is invalid? - // e.g. 1-2-3 with 10-20-30, the minimum of the latter is - // bigger than the maximum of the former. - minSize = qMax(firstEdge->minSize, secondEdge->minSize); maxSize = qMin(firstEdge->maxSize, secondEdge->maxSize); + // This condition means that the maximum size of one anchor being simplified is smaller than + // the minimum size of the other anchor. The consequence is that there won't be a valid size + // for this parallel setup. + if (minSize > maxSize) { + return false; + } + expSize = qMax(firstEdge->expSize, secondEdge->expSize); expSize = qMin(expSize, maxSize); @@ -258,6 +268,8 @@ void ParallelAnchorData::refreshSizeHints_helper(qreal effectiveSpacing, sizeAtPreferred = prefSize; sizeAtExpanding = prefSize; sizeAtMaximum = prefSize; + + return true; } /*! @@ -362,12 +374,12 @@ void SequentialAnchorData::updateChildrenSizes() } } -void SequentialAnchorData::refreshSizeHints(qreal effectiveSpacing) +bool SequentialAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) { - refreshSizeHints_helper(effectiveSpacing); + return refreshSizeHints_helper(styleInfo); } -void SequentialAnchorData::refreshSizeHints_helper(qreal effectiveSpacing, +bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren) { minSize = 0; @@ -379,8 +391,8 @@ void SequentialAnchorData::refreshSizeHints_helper(qreal effectiveSpacing, AnchorData *edge = m_edges.at(i); // If it's the case refresh children information first - if (refreshChildren) - edge->refreshSizeHints(effectiveSpacing); + if (refreshChildren && !edge->refreshSizeHints(styleInfo)) + return false; minSize += edge->minSize; prefSize += edge->prefSize; @@ -393,6 +405,8 @@ void SequentialAnchorData::refreshSizeHints_helper(qreal effectiveSpacing, sizeAtPreferred = prefSize; sizeAtExpanding = prefSize; sizeAtMaximum = prefSize; + + return true; } #ifdef QT_DEBUG @@ -458,7 +472,7 @@ QString GraphPath::toString() const #endif QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() - : calculateGraphCacheDirty(1) + : calculateGraphCacheDirty(true), styleInfoDirty(true) { for (int i = 0; i < NOrientations; ++i) { for (int j = 0; j < 3; ++j) { @@ -510,18 +524,49 @@ inline static qreal checkAdd(qreal a, qreal b) } /*! - * \internal - * - * Takes the sequence of vertices described by (\a before, \a vertices, \a after) and replaces - * all anchors connected to the vertices in \a vertices with one simplified anchor between - * \a before and \a after. The simplified anchor will be a placeholder for all the previous - * anchors between \a before and \a after, and can be restored back to the anchors it is a - * placeholder for. - */ -static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph, - AnchorVertex *before, - const QVector<AnchorVertex*> &vertices, - AnchorVertex *after) + \internal + + Adds \a newAnchor to the graph \a g. + + Returns the newAnchor itself if it could be added without further changes to the graph. If a + new parallel anchor had to be created, then returns the new parallel anchor. In case the + addition is unfeasible -- because a parallel setup is not possible, returns 0. +*/ +static AnchorData *addAnchorMaybeParallel(Graph<AnchorVertex, AnchorData> *g, + AnchorData *newAnchor) +{ + bool feasible = true; + + // If already exists one anchor where newAnchor is supposed to be, we create a parallel + // anchor. + if (AnchorData *oldAnchor = g->takeEdge(newAnchor->from, newAnchor->to)) { + ParallelAnchorData *parallel = new ParallelAnchorData(oldAnchor, newAnchor); + + // At this point we can identify that the parallel anchor is not feasible, e.g. one + // anchor minimum size is bigger than the other anchor maximum size. + feasible = parallel->refreshSizeHints_helper(0, false); + newAnchor = parallel; + } + + g->createEdge(newAnchor->from, newAnchor->to, newAnchor); + return feasible ? newAnchor : 0; +} + + +/*! + \internal + + Takes the sequence of vertices described by (\a before, \a vertices, \a after) and removes + all anchors connected to the vertices in \a vertices, returning one simplified anchor between + \a before and \a after. + + Note that this function doesn't add the created anchor to the graph. This should be done by + the caller. +*/ +static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *graph, + AnchorVertex *before, + const QVector<AnchorVertex*> &vertices, + AnchorVertex *after) { AnchorData *data = graph->edgeData(before, vertices.first()); Q_ASSERT(data); @@ -546,41 +591,24 @@ static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph, qDebug("simplifying [%s] to [%s - %s]", qPrintable(strPath), qPrintable(before->toString()), qPrintable(after->toString())); #endif - SequentialAnchorData *sequence = new SequentialAnchorData; AnchorVertex *prev = before; + QVector<AnchorData *> edges; for (int i = 0; i <= orderedVertices.count(); ++i) { AnchorVertex *next = (i < orderedVertices.count()) ? orderedVertices.at(i) : after; AnchorData *ad = graph->takeEdge(prev, next); Q_ASSERT(ad); - sequence->m_edges.append(ad); + edges.append(ad); prev = next; } - sequence->setVertices(orderedVertices); + SequentialAnchorData *sequence = new SequentialAnchorData(orderedVertices, edges); sequence->from = before; sequence->to = after; sequence->refreshSizeHints_helper(0, false); - // Note that since layout 'edges' can't be simplified away from - // the graph, it's safe to assume that if there's a layout - // 'edge', it'll be in the boundaries of the sequence. - sequence->isLayoutAnchor = (sequence->m_edges.first()->isLayoutAnchor - || sequence->m_edges.last()->isLayoutAnchor); - - AnchorData *newAnchor = sequence; - if (AnchorData *oldAnchor = graph->takeEdge(before, after)) { - ParallelAnchorData *parallel = new ParallelAnchorData(oldAnchor, sequence); - parallel->isLayoutAnchor = (oldAnchor->isLayoutAnchor - || sequence->isLayoutAnchor); - parallel->refreshSizeHints_helper(0, false); - newAnchor = parallel; - } - graph->createEdge(before, after, newAnchor); - - // True if we created a parallel anchor - return newAnchor != sequence; + return sequence; } /*! @@ -617,15 +645,17 @@ static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph, 2. Go to (1) 3. Done + When creating the parallel anchors, the algorithm might identify unfeasible situations. In this + case the simplification process stops and returns false. Otherwise returns true. */ -void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) +bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) { static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); if (noSimplification || items.isEmpty()) - return; + return true; if (graphSimplified[orientation]) - return; + return true; graphSimplified[orientation] = true; #if 0 @@ -634,12 +664,18 @@ void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) #endif if (!graph[orientation].rootVertex()) - return; + return true; bool dirty; + bool feasible = true; do { - dirty = simplifyGraphIteration(orientation); - } while (dirty); + dirty = simplifyGraphIteration(orientation, &feasible); + } while (dirty && feasible); + + if (!feasible) + graphSimplified[orientation] = false; + + return feasible; } /*! @@ -656,7 +692,8 @@ void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) Note that there are some catches to this that are not covered by the above explanation, see the function comments for more details. */ -bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation) +bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutPrivate::Orientation orientation, + bool *feasible) { Q_Q(QGraphicsAnchorLayout); Graph<AnchorVertex, AnchorData> &g = graph[orientation]; @@ -667,8 +704,6 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP QVector<AnchorVertex*> candidates; bool candidatesForward; - const Qt::AnchorPoint centerEdge = pickEdge(Qt::AnchorHorizontalCenter, orientation); - // Walk depth-first, in the stack we store start of the candidate sequence (beforeSequence) // and the vertex to be visited. while (!stack.isEmpty()) { @@ -777,7 +812,8 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP // One restriction we have is to not simplify half of an anchor and let the other half // unsimplified. So we remove center edges before and after the sequence. - if (beforeSequence->m_edge == centerEdge && beforeSequence->m_item == candidates.first()->m_item) { + const AnchorData *firstAnchor = g.edgeData(beforeSequence, candidates.first()); + if (firstAnchor->isCenterAnchor) { beforeSequence = candidates.first(); candidates.remove(0); @@ -786,7 +822,8 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP continue; } - if (afterSequence->m_edge == centerEdge && afterSequence->m_item == candidates.last()->m_item) { + const AnchorData *lastAnchor = g.edgeData(candidates.last(), afterSequence); + if (lastAnchor->isCenterAnchor) { afterSequence = candidates.last(); candidates.remove(candidates.count() - 1); @@ -794,11 +831,26 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraphIteration(QGraphicsAnchorLayoutP continue; } - // This function will remove the candidates from the graph and create one edge between - // beforeSequence and afterSequence. This function returns true if the sequential - // simplification also caused a parallel simplification to be created. In this case we end - // the iteration and start again (since all the visited state we have may be outdated). - if (simplifySequentialChunk(&g, beforeSequence, candidates, afterSequence)) + // + // Add the sequence to the graph. + // + + AnchorData *sequence = createSequence(&g, beforeSequence, candidates, afterSequence); + + // If 'beforeSequence' and 'afterSequence' already had an anchor between them, we'll + // create a parallel anchor between the new sequence and the old anchor. + AnchorData *newAnchor = addAnchorMaybeParallel(&g, sequence); + + if (!newAnchor) { + *feasible = false; + return false; + } + + // When a new parallel anchor is create in the graph, we finish the iteration and return + // true to indicate a new iteration is needed. This happens because a parallel anchor + // changes the number of adjacents one vertex has, possibly opening up oportunities for + // building candidate lists (when adjacents == 2). + if (newAnchor != sequence) return true; // If there was no parallel simplification, we'll keep walking the graph. So we clear the @@ -1008,11 +1060,13 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( AnchorData *data = new AnchorData; c->variables.insert(data, 1.0); addAnchor_helper(item, firstEdge, item, centerEdge, data); + data->isCenterAnchor = true; data->refreshSizeHints(0); data = new AnchorData; c->variables.insert(data, -1.0); addAnchor_helper(item, centerEdge, item, lastEdge, data); + data->isCenterAnchor = true; data->refreshSizeHints(0); itemCenterConstraints[orientation].append(c); @@ -1234,9 +1288,11 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt { Q_Q(QGraphicsAnchorLayout); + const Orientation orientation = edgeOrientation(firstEdge); + // Guarantee that the graph is no simplified when adding this anchor, // anchor manipulation always happen in the full graph - restoreSimplifiedGraph(edgeOrientation(firstEdge)); + restoreSimplifiedGraph(orientation); // Is the Vertex (firstItem, firstEdge) already represented in our // internal structure? @@ -1245,10 +1301,16 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt // Remove previous anchor // ### Could we update the existing edgeData rather than creating a new one? - if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) { + if (graph[orientation].edgeData(v1, v2)) { removeAnchor_helper(v1, v2); } + // If its an internal anchor, set the associated item + if (firstItem == secondItem) + data->item = firstItem; + + data->orientation = orientation; + // Create a bi-directional edge in the sense it can be transversed both // from v1 or v2. "data" however is shared between the two references // so we still know that the anchor direction is from 1 to 2. @@ -1257,10 +1319,11 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt #ifdef QT_DEBUG data->name = QString::fromAscii("%1 --to--> %2").arg(v1->toString()).arg(v2->toString()); #endif - // Keep track of anchors that are connected to the layout 'edges' - data->isLayoutAnchor = (v1->m_item == q || v2->m_item == q); + // ### bit to track internal anchors, since inside AnchorData methods + // we don't have access to the 'q' pointer. + data->isLayoutAnchor = (data->item == q); - graph[edgeOrientation(firstEdge)].createEdge(v1, v2, data); + graph[orientation].createEdge(v1, v2, data); } QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *firstItem, @@ -1425,7 +1488,7 @@ void QGraphicsAnchorLayoutPrivate::anchorSize(const AnchorData *data, Q_ASSERT(minSize || prefSize || maxSize); Q_ASSERT(data); QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate *>(this); - that->restoreSimplifiedGraph(edgeOrientation(data->from->m_edge)); + that->restoreSimplifiedGraph(Orientation(data->orientation)); if (minSize) *minSize = data->minSize; @@ -1565,34 +1628,32 @@ void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&fi } } -qreal QGraphicsAnchorLayoutPrivate::effectiveSpacing(Orientation orientation) const +QLayoutStyleInfo &QGraphicsAnchorLayoutPrivate::styleInfo() const { - Q_Q(const QGraphicsAnchorLayout); - qreal s = spacings[orientation]; - if (s < 0) { - // ### make sure behaviour is the same as in QGraphicsGridLayout + if (styleInfoDirty) { + Q_Q(const QGraphicsAnchorLayout); + //### Fix this if QGV ever gets support for Metal style or different Aqua sizes. + QWidget *wid = 0; + QGraphicsLayoutItem *parent = q->parentLayoutItem(); while (parent && parent->isLayout()) { parent = parent->parentLayoutItem(); } + QGraphicsWidget *w = 0; if (parent) { QGraphicsItem *parentItem = parent->graphicsItem(); - if (parentItem && parentItem->isWidget()) { - QGraphicsWidget *w = static_cast<QGraphicsWidget*>(parentItem); - s = w->style()->pixelMetric(orientation == Horizontal - ? QStyle::PM_LayoutHorizontalSpacing - : QStyle::PM_LayoutVerticalSpacing); - } + if (parentItem && parentItem->isWidget()) + w = static_cast<QGraphicsWidget*>(parentItem); } - } - // ### Currently we do not support negative anchors inside the graph. - // To avoid those being created by a negative style spacing, we must - // make this test. - if (s < 0) - s = 0; + QStyle *style = w ? w->style() : QApplication::style(); + cachedStyleInfo = QLayoutStyleInfo(style, wid); + cachedStyleInfo.setDefaultSpacing(Qt::Horizontal, spacings[0]); + cachedStyleInfo.setDefaultSpacing(Qt::Vertical, spacings[1]); - return s; + styleInfoDirty = false; + } + return cachedStyleInfo; } /*! @@ -1620,7 +1681,7 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs() dumpGraph(QString::fromAscii("%1-after").arg(count)); #endif - calculateGraphCacheDirty = 0; + calculateGraphCacheDirty = false; } // ### Maybe getGraphParts could return the variables when traversing, at least @@ -1638,38 +1699,52 @@ QList<AnchorData *> getVariables(QList<QSimplexConstraint *> constraints) } /*! - \internal + \internal - Calculate graphs is the method that puts together all the helper routines - so that the AnchorLayout can calculate the sizes of each item. + Calculate graphs is the method that puts together all the helper routines + so that the AnchorLayout can calculate the sizes of each item. - In a nutshell it should do: + In a nutshell it should do: - 1) Update anchor nominal sizes, that is, the size that each anchor would - have if no other restrictions applied. This is done by quering the - layout style and the sizeHints of the items belonging to the layout. + 1) Refresh anchor nominal sizes, that is, the size that each anchor would + have if no other restrictions applied. This is done by quering the + layout style and the sizeHints of the items belonging to the layout. - 2) Simplify the graph by grouping together parallel and sequential anchors - into "group anchors". These have equivalent minimum, preferred and maximum - sizeHints as the anchors they replace. + 2) Simplify the graph by grouping together parallel and sequential anchors + into "group anchors". These have equivalent minimum, preferred and maximum + sizeHints as the anchors they replace. - 3) Check if we got to a trivial case. In some cases, the whole graph can be - simplified into a single anchor. If so, use this information. If not, - then call the Simplex solver to calculate the anchors sizes. + 3) Check if we got to a trivial case. In some cases, the whole graph can be + simplified into a single anchor. If so, use this information. If not, + then call the Simplex solver to calculate the anchors sizes. - 4) Once the root anchors had its sizes calculated, propagate that to the - anchors they represent. + 4) Once the root anchors had its sizes calculated, propagate that to the + anchors they represent. */ void QGraphicsAnchorLayoutPrivate::calculateGraphs( QGraphicsAnchorLayoutPrivate::Orientation orientation) { Q_Q(QGraphicsAnchorLayout); - // Simplify the graph - simplifyGraph(orientation); +#if defined(QT_DEBUG) || defined(Q_AUTOTEST_EXPORT) + lastCalculationUsedSimplex[orientation] = false; +#endif - // Reset the nominal sizes of each anchor based on the current item sizes - setAnchorSizeHintsFromItems(orientation); + // Reset the nominal sizes of each anchor based on the current item sizes. This function + // works with both simplified and non-simplified graphs, so it'll work when the + // simplification is going to be reused. + if (!refreshAllSizeHints(orientation)) { + qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); + graphHasConflicts[orientation] = true; + return; + } + + // Simplify the graph + if (!simplifyGraph(orientation)) { + qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); + graphHasConflicts[orientation] = true; + return; + } // Traverse all graph edges and store the possible paths to each vertex findPaths(orientation); @@ -1837,23 +1912,31 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstra } /*! - \internal + \internal + + Traverse the graph refreshing the size hints. Complex anchors will call the + refresh method of their children anchors. Simple anchors, if are internal + anchors, will query the associated item for their size hints. - For graph edges ("anchors") that represent items, this method updates their - intrinsic size restrictions, based on the item size hints. + Returns false if some unfeasibility was found in the graph regarding the + complex anchors. */ -void QGraphicsAnchorLayoutPrivate::setAnchorSizeHintsFromItems(Orientation orientation) +bool QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation) { Graph<AnchorVertex, AnchorData> &g = graph[orientation]; QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections(); - qreal spacing = effectiveSpacing(orientation); - + QLayoutStyleInfo styleInf = styleInfo(); for (int i = 0; i < vertices.count(); ++i) { AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);; Q_ASSERT(data->from && data->to); - data->refreshSizeHints(spacing); + + // During the traversal we check the feasibility of the complex anchors. + if (!data->refreshSizeHints(&styleInf)) + return false; } + + return true; } /*! @@ -1960,17 +2043,27 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin { QList<QSimplexConstraint *> anchorConstraints; for (int i = 0; i < anchors.size(); ++i) { - QSimplexConstraint *c = new QSimplexConstraint; - c->variables.insert(anchors[i], 1.0); - c->constant = anchors[i]->minSize; - c->ratio = QSimplexConstraint::MoreOrEqual; - anchorConstraints += c; - - c = new QSimplexConstraint; - c->variables.insert(anchors[i], 1.0); - c->constant = anchors[i]->maxSize; - c->ratio = QSimplexConstraint::LessOrEqual; - anchorConstraints += c; + AnchorData *ad = anchors[i]; + + if ((ad->minSize == ad->maxSize) || qFuzzyCompare(ad->minSize, ad->maxSize)) { + QSimplexConstraint *c = new QSimplexConstraint; + c->variables.insert(ad, 1.0); + c->constant = ad->minSize; + c->ratio = QSimplexConstraint::Equal; + anchorConstraints += c; + } else { + QSimplexConstraint *c = new QSimplexConstraint; + c->variables.insert(ad, 1.0); + c->constant = ad->minSize; + c->ratio = QSimplexConstraint::MoreOrEqual; + anchorConstraints += c; + + c = new QSimplexConstraint; + c->variables.insert(ad, 1.0); + c->constant = ad->maxSize; + c->ratio = QSimplexConstraint::LessOrEqual; + anchorConstraints += c; + } } return anchorConstraints; @@ -2110,8 +2203,8 @@ void QGraphicsAnchorLayoutPrivate::identifyNonFloatItems_helper(const AnchorData switch(ad->type) { case AnchorData::Normal: - if (ad->from->m_item == ad->to->m_item && ad->to->m_item != q) - nonFloatingItemsIdentifiedSoFar->insert(ad->to->m_item); + if (ad->item && ad->item != q) + nonFloatingItemsIdentifiedSoFar->insert(ad->item); break; case AnchorData::Sequential: foreach (const AnchorData *d, static_cast<const SequentialAnchorData *>(ad)->m_edges) @@ -2377,7 +2470,7 @@ bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> *min = simplex.solveMin(); // Save sizeAtMinimum results - QList<QSimplexVariable *> variables = simplex.constraintsVariables(); + QList<AnchorData *> variables = getVariables(constraints); for (int i = 0; i < variables.size(); ++i) { AnchorData *ad = static_cast<AnchorData *>(variables[i]); Q_ASSERT(ad->result >= ad->minSize || qFuzzyCompare(ad->result, ad->minSize)); @@ -2536,7 +2629,7 @@ void QGraphicsAnchorLayoutPrivate::solveExpanding(const QList<QSimplexConstraint hasExpanding = true; // Lock anchor between boundedExpSize and sizeAtMaximum (ensure 3.a) - if (boundedExpSize == ad->sizeAtMaximum) { + if (boundedExpSize == ad->sizeAtMaximum || qFuzzyCompare(boundedExpSize, ad->sizeAtMaximum)) { // The interval has only one possible value, we can use an "Equal" // constraint and don't need to add this variable to the objective. QSimplexConstraint *itemC = new QSimplexConstraint; @@ -2635,3 +2728,4 @@ void QGraphicsAnchorLayoutPrivate::dumpGraph(const QString &name) #endif QT_END_NAMESPACE +#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index d45c004..7dd0d65 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -60,7 +60,7 @@ #include "qgraphicsanchorlayout.h" #include "qgraph_p.h" #include "qsimplex_p.h" - +#ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE /* @@ -151,15 +151,16 @@ struct AnchorData : public QSimplexVariable { }; AnchorData() - : QSimplexVariable(), from(0), to(0), + : QSimplexVariable(), item(0), from(0), to(0), minSize(0), prefSize(0), expSize(0), maxSize(0), sizeAtMinimum(0), sizeAtPreferred(0), sizeAtExpanding(0), sizeAtMaximum(0), graphicsAnchor(0), skipInPreferred(0), - type(Normal), hasSize(true), isLayoutAnchor(false) {} + type(Normal), hasSize(true), isLayoutAnchor(false), + isCenterAnchor(false), orientation(0) {} virtual void updateChildrenSizes() {} - virtual void refreshSizeHints(qreal effectiveSpacing); + virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); virtual ~AnchorData() {} @@ -180,6 +181,9 @@ struct AnchorData : public QSimplexVariable { hasSize = false; } + // Internal anchors have associated items + QGraphicsLayoutItem *item; + // Anchor is semantically directed AnchorVertex *from; AnchorVertex *to; @@ -205,7 +209,9 @@ struct AnchorData : public QSimplexVariable { uint skipInPreferred : 1; uint type : 2; // either Normal, Sequential or Parallel uint hasSize : 1; // if false, get size from style. - uint isLayoutAnchor : 1; // if this anchor is connected to a layout 'edge' + uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor + uint isCenterAnchor : 1; + uint orientation : 1; }; #ifdef QT_DEBUG @@ -217,26 +223,20 @@ inline QString AnchorData::toString() const struct SequentialAnchorData : public AnchorData { - SequentialAnchorData() : AnchorData() + SequentialAnchorData(const QVector<AnchorVertex *> &vertices, const QVector<AnchorData *> &edges) + : AnchorData(), m_children(vertices), m_edges(edges) { type = AnchorData::Sequential; + orientation = m_edges.at(0)->orientation; #ifdef QT_DEBUG - name = QLatin1String("SequentialAnchorData"); + name = QString::fromAscii("%1 -- %2").arg(vertices.first()->toString(), vertices.last()->toString()); #endif } virtual void updateChildrenSizes(); - virtual void refreshSizeHints(qreal effectiveSpacing); + virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); - void refreshSizeHints_helper(qreal effectiveSpacing, bool refreshChildren = true); - - void setVertices(const QVector<AnchorVertex*> &vertices) - { - m_children = vertices; -#ifdef QT_DEBUG - name = QString::fromAscii("%1 -- %2").arg(vertices.first()->toString(), vertices.last()->toString()); -#endif - } + bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true); QVector<AnchorVertex*> m_children; // list of vertices in the sequence QVector<AnchorData*> m_edges; // keep the list of edges too. @@ -248,6 +248,7 @@ struct ParallelAnchorData : public AnchorData : AnchorData(), firstEdge(first), secondEdge(second) { type = AnchorData::Parallel; + orientation = first->orientation; // ### Those asserts force that both child anchors have the same direction, // but can't we simplify a pair of anchors in opposite directions? @@ -261,9 +262,9 @@ struct ParallelAnchorData : public AnchorData } virtual void updateChildrenSizes(); - virtual void refreshSizeHints(qreal effectiveSpacing); + virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); - void refreshSizeHints_helper(qreal effectiveSpacing, bool refreshChildren = true); + bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true); AnchorData* firstEdge; AnchorData* secondEdge; @@ -423,13 +424,12 @@ public: Qt::AnchorPoint &firstEdge, QGraphicsLayoutItem *&secondItem, Qt::AnchorPoint &secondEdge); - // for getting the actual spacing (will query the style if the - // spacing is not explicitly set). - qreal effectiveSpacing(Orientation orientation) const; + + QLayoutStyleInfo &styleInfo() const; // Activation methods - void simplifyGraph(Orientation orientation); - bool simplifyGraphIteration(Orientation orientation); + bool simplifyGraph(Orientation orientation); + bool simplifyGraphIteration(Orientation orientation, bool *feasible); void restoreSimplifiedGraph(Orientation orientation); void calculateGraphs(); @@ -441,7 +441,7 @@ public: bool calculateNonTrunk(const QList<QSimplexConstraint *> &constraints, const QList<AnchorData *> &variables); - void setAnchorSizeHintsFromItems(Orientation orientation); + bool refreshAllSizeHints(Orientation orientation); void findPaths(Orientation orientation); void constraintsFromPaths(Orientation orientation); void updateAnchorSizes(Orientation orientation); @@ -524,10 +524,13 @@ public: #endif uint calculateGraphCacheDirty : 1; + mutable uint styleInfoDirty : 1; + mutable QLayoutStyleInfo cachedStyleInfo; friend class QGraphicsAnchorPrivate; }; QT_END_NAMESPACE +#endif //QT_NO_GRAPHICSVIEW #endif diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 45627f6..d70b039 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1039,13 +1039,31 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } // Update focus scope item ptr in new scope. - if (newParent) { + QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; + if (newFocusScopeItem && newParent) { + if (subFocusItem) { + // Find the subFocusItem's topmost focus scope. + QGraphicsItem *ancestorScope = 0; + QGraphicsItem *p = subFocusItem->d_ptr->parent; + while (p) { + if (p->flags() & QGraphicsItem::ItemIsFocusScope) + ancestorScope = p; + if (p->isPanel()) + break; + p = p->parentItem(); + } + if (ancestorScope) + newFocusScopeItem = ancestorScope; + } + QGraphicsItem *p = newParent; while (p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) { - p->d_ptr->focusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; - // ### The below line might not make sense... - if (subFocusItem) + p->d_ptr->focusScopeItem = newFocusScopeItem; + // Ensure the new item is no longer the subFocusItem. The + // only way to set focus on a child of a focus scope is + // by setting focus on the scope itself. + if (subFocusItem && !p->focusItem()) subFocusItem->d_ptr->clearSubFocus(); break; } @@ -1228,7 +1246,8 @@ void QGraphicsItemCache::purge() } /*! - Constructs a QGraphicsItem with the given \a parent. + Constructs a QGraphicsItem with the given \a parent item. + It does not modify the parent object returned by QObject::parent(). If \a parent is 0, you can add the item to a scene by calling QGraphicsScene::addItem(). The item will then become a top-level item. @@ -1286,6 +1305,8 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, */ QGraphicsItem::~QGraphicsItem() { + if (d_ptr->isObject) + QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true; d_ptr->inDestructor = 1; d_ptr->removeExtraItemCache(); @@ -1511,6 +1532,8 @@ const QGraphicsObject *QGraphicsItem::toGraphicsObject() const the parent. You should not \l{QGraphicsScene::addItem()}{add} the item to the scene yourself. + Calling this function on an item that is an ancestor of \a parent have undefined behaviour. + \sa parentItem(), childItems() */ void QGraphicsItem::setParentItem(QGraphicsItem *parent) @@ -1655,7 +1678,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); // Flags that alter the geometry of the item (or its children). - const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); + const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable); bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask); if (fullUpdate) d_ptr->paintedViewBoundingRectsNeedRepaint = 1; @@ -2482,12 +2505,14 @@ void QGraphicsItem::setOpacity(qreal opacity) itemChange(ItemOpacityHasChanged, newOpacityVariant); // Update. - if (d_ptr->scene) + if (d_ptr->scene) { + d_ptr->invalidateGraphicsEffectsRecursively(); d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*maybeDirtyClipPath=*/false, /*force=*/false, /*ignoreOpacity=*/true); + } if (d_ptr->isObject) emit static_cast<QGraphicsObject *>(this)->opacityChanged(); @@ -2977,8 +3002,11 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim while (p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) { p->d_ptr->focusScopeItem = q_ptr; - if (!q_ptr->isActive() || !p->focusItem()) + if (!p->focusItem()) { + // If you call setFocus on a child of a focus scope that + // doesn't currently have a focus item, then stop. return; + } break; } p = p->d_ptr->parent; @@ -4259,7 +4287,7 @@ void QGraphicsItem::stackBefore(const QGraphicsItem *sibling) // Only move items with the same Z value, and that need moving. int siblingIndex = sibling->d_ptr->siblingIndex; int myIndex = d_ptr->siblingIndex; - if (myIndex >= siblingIndex && d_ptr->z == sibling->d_ptr->z) { + if (myIndex >= siblingIndex) { siblings->move(myIndex, siblingIndex); // Fixup the insertion ordering. for (int i = 0; i < siblings->size(); ++i) { @@ -4735,7 +4763,7 @@ bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const { if (!item) return false; - return QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(item, this) + return qt_closestItemFirst(item, this) && qt_QGraphicsItem_isObscured(this, item, boundingRect()); } @@ -4949,6 +4977,22 @@ int QGraphicsItemPrivate::depth() const /*! \internal */ +void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively() +{ + QGraphicsItemPrivate *itemPrivate = this; + do { + if (itemPrivate->graphicsEffect) { + itemPrivate->notifyInvalidated = 1; + + if (!itemPrivate->updateDueToGraphicsEffect) + static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache(); + } + } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0)); +} + +/*! + \internal +*/ void QGraphicsItemPrivate::invalidateDepthRecursively() { if (itemDepth == -1) @@ -5280,11 +5324,7 @@ void QGraphicsItem::update(const QRectF &rect) return; // Make sure we notify effects about invalidated source. - QGraphicsItem *item = this; - do { - if (item->d_ptr->graphicsEffect) - item->d_ptr->notifyInvalidated = 1; - } while ((item = item->d_ptr->parent)); + d_ptr->invalidateGraphicsEffectsRecursively(); if (CacheMode(d_ptr->cacheMode) != NoCache) { // Invalidate cache. @@ -7267,6 +7307,21 @@ static void qt_graphicsItem_highlightSelected( The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms. It maps many of QGraphicsItem's basic setters and getters to properties and adds notification signals for many of them. + + \section1 Parents and Children + + Each graphics object can be constructed with a parent item. This ensures that the + item will be destroyed when its parent item is destroyed. Although QGraphicsObject + inherits from both QObject and QGraphicsItem, you should use the functions provided + by QGraphicsItem, \e not QObject, to manage the relationships between parent and + child items. + + The relationships between items can be explored using the parentItem() and childItems() + functions. In the hierarchy of items in a scene, the parentObject() and parentWidget() + functions are the equivalent of the QWidget::parent() and QWidget::parentWidget() + functions for QWidget subclasses. + + \sa QGraphicsWidget */ /*! @@ -7304,6 +7359,9 @@ void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureContext co \property QGraphicsObject::parent \brief the parent of the item + \note The item's parent is set independently of the parent object returned + by QObject::parent(). + \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject() */ @@ -9122,10 +9180,14 @@ void QGraphicsPixmapItem::setOffset(const QPointF &offset) QRectF QGraphicsPixmapItem::boundingRect() const { Q_D(const QGraphicsPixmapItem); - qreal pw = 1.0; if (d->pixmap.isNull()) return QRectF(); - return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); + if (d->flags & ItemIsSelectable) { + qreal pw = 1.0; + return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2); + } else { + return QRectF(d->offset, d->pixmap.size()); + } } /*! @@ -9635,12 +9697,14 @@ bool QGraphicsTextItem::sceneEvent(QEvent *event) // Reset the focus widget's input context, regardless // of how this item gained or lost focus. if (QWidget *fw = qApp->focusWidget()) { +#ifndef QT_NO_IM if (QInputContext *qic = fw->inputContext()) { if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut) qic->reset(); else qic->update(); } +#endif //QT_NO_IM } break; default: @@ -10644,7 +10708,8 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) } } -QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const { const bool deviceCoordinates = (system == Qt::DeviceCoordinates); if (!info && deviceCoordinates) { @@ -10658,7 +10723,17 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); const QRectF sourceRect = boundingRect(system); - QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + QRect effectRect; + + if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) { + effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) { + // adjust by 1.5 to account for cosmetic pens + effectRect = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5).toAlignedRect(); + } else { + effectRect = sourceRect.toAlignedRect(); + } + if (offset) *offset = effectRect.topLeft(); @@ -10686,10 +10761,15 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP effectRect.setBottom(deviceHeight -1); } - if (effectRect.isEmpty()) return QPixmap(); + if (system == Qt::LogicalCoordinates + && effectRect.size() == sourceRect.size() + && isPixmap()) { + return static_cast<QGraphicsPixmapItem *>(item)->pixmap(); + } + QPixmap pixmap(effectRect.size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); @@ -10721,6 +10801,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP } pixmapPainter.end(); + return pixmap; } @@ -10732,14 +10813,35 @@ QDebug operator<<(QDebug debug, QGraphicsItem *item) return debug; } - debug << "QGraphicsItem(this =" << ((void*)item) - << ", parent =" << ((void*)item->parentItem()) + if (QGraphicsObject *o = item->toGraphicsObject()) + debug << o->metaObject()->className(); + else + debug << "QGraphicsItem"; + debug << "(this =" << (void*)item + << ", parent =" << (void*)item->parentItem() << ", pos =" << item->pos() << ", z =" << item->zValue() << ", flags = " << item->flags() << ")"; return debug; } +QDebug operator<<(QDebug debug, QGraphicsObject *item) +{ + if (!item) { + debug << "QGraphicsObject(0)"; + return debug; + } + + debug.nospace() << item->metaObject()->className() << '(' << (void*)item; + if (!item->objectName().isEmpty()) + debug << ", name = " << item->objectName(); + debug.nospace() << ", parent = " << ((void*)item->parentItem()) + << ", pos = " << item->pos() + << ", z = " << item->zValue() << ", flags = " + << item->flags() << ')'; + return debug.space(); +} + QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change) { const char *str = "UnknownChange"; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 2665235..f3fe99c 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -555,7 +555,7 @@ public: using QObject::children; #endif - void grabGesture(Qt::GestureType type, Qt::GestureContext context = Qt::WidgetWithChildrenGesture); + void grabGesture(Qt::GestureType type, Qt::GestureContext context = Qt::ItemWithChildrenGesture); Q_SIGNALS: void parentChanged(); @@ -1120,6 +1120,7 @@ template <class T> inline T qgraphicsitem_cast(const QGraphicsItem *item) #ifndef QT_NO_DEBUG_STREAM Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem *item); +Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsObject *item); Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change); Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag); Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 6550362..ca56c18 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -61,6 +61,7 @@ #include <private/qgraphicstransform_p.h> #include <private/qgraphicseffect_p.h> +#include <qgraphicseffect.h> #include <QtCore/qpoint.h> @@ -177,6 +178,7 @@ public: wantsActive(0), holesInSiblingIndex(0), sequentialOrdering(1), + updateDueToGraphicsEffect(0), globalStackingOrder(-1), q_ptr(0) { @@ -221,6 +223,7 @@ public: bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; int depth() const; + void invalidateGraphicsEffectsRecursively(); void invalidateDepthRecursively(); void resolveDepth(); void addChild(QGraphicsItem *child); @@ -502,6 +505,7 @@ public: quint32 wantsActive : 1; quint32 holesInSiblingIndex : 1; quint32 sequentialOrdering : 1; + quint32 updateDueToGraphicsEffect : 1; // Optional stacking order int globalStackingOrder; @@ -589,16 +593,21 @@ public: inline const QWidget *widget() const { return 0; } - inline void update() - { item->update(); } + inline void update() { + item->d_ptr->updateDueToGraphicsEffect = true; + item->update(); + item->d_ptr->updateDueToGraphicsEffect = false; + } inline void effectBoundingRectChanged() { item->prepareGeometryChange(); } inline bool isPixmap() const { - return (item->type() == QGraphicsPixmapItem::Type); - //|| (item->d_ptr->isObject && qobject_cast<QFxImage *>(q_func())); + return item->type() == QGraphicsPixmapItem::Type + && !(item->flags() & QGraphicsItem::ItemIsSelectable) + && item->d_ptr->children.size() == 0; + //|| (item->d_ptr->isObject && qobject_cast<QmlGraphicsImage *>(q_func())); } inline const QStyleOption *styleOption() const @@ -615,14 +624,82 @@ public: QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *); - QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; + QPixmap pixmap(Qt::CoordinateSystem system, + QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const; QGraphicsItem *item; QGraphicsItemPaintInfo *info; + QTransform lastEffectTransform; }; /*! + Returns true if \a item1 is on top of \a item2. + The items dont need to be siblings. + + \internal +*/ +inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Siblings? Just check their z-values. + const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); + const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); + if (d1->parent == d2->parent) + return qt_closestLeaf(item1, item2); + + // Find common ancestor, and each item's ancestor closest to the common + // ancestor. + int item1Depth = d1->depth(); + int item2Depth = d2->depth(); + const QGraphicsItem *p = item1; + const QGraphicsItem *t1 = item1; + while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { + if (p == item2) { + // item2 is one of item1's ancestors; item1 is on top + return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t1 = p; + --item1Depth; + } + p = item2; + const QGraphicsItem *t2 = item2; + while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { + if (p == item1) { + // item1 is one of item2's ancestors; item1 is not on top + return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t2 = p; + --item2Depth; + } + + // item1Ancestor is now at the same level as item2Ancestor, but not the same. + const QGraphicsItem *p1 = t1; + const QGraphicsItem *p2 = t2; + while (t1 && t1 != t2) { + p1 = t1; + p2 = t2; + t1 = t1->d_ptr->parent; + t2 = t2->d_ptr->parent; + } + + // in case we have a common ancestor, we compare the immediate children in the ancestor's path. + // otherwise we compare the respective items' topLevelItems directly. + return qt_closestLeaf(p1, p2); +} + +/*! + Returns true if \a item2 is on top of \a item1. + The items dont need to be siblings. + + \internal +*/ +inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return qt_closestItemFirst(item2, item1); +} + +/*! \internal */ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) @@ -642,7 +719,7 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item /*! \internal */ -static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) { return qt_closestLeaf(item2, item1); } /* diff --git a/src/gui/graphicsview/qgraphicslayout_p.h b/src/gui/graphicsview/qgraphicslayout_p.h index 59c6dba..4aeae39 100644 --- a/src/gui/graphicsview/qgraphicslayout_p.h +++ b/src/gui/graphicsview/qgraphicslayout_p.h @@ -60,6 +60,8 @@ #include "qgraphicslayout.h" #include "qgraphicslayoutitem_p.h" #include <QtGui/qstyle.h> +#include <QtGui/qwidget.h> +#include <QtGui/qstyleoption.h> QT_BEGIN_NAMESPACE @@ -76,6 +78,55 @@ inline bool qt_graphicsLayoutDebug() } #endif + +class QLayoutStyleInfo +{ +public: + inline QLayoutStyleInfo() { invalidate(); } + inline QLayoutStyleInfo(QStyle *style, QWidget *widget) + : m_valid(true), m_style(style), m_widget(widget) + { + Q_ASSERT(style); + if (widget) //### + m_styleOption.initFrom(widget); + m_defaultSpacing[0] = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); + m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing); + } + + inline void invalidate() { m_valid = false; m_style = 0; m_widget = 0; } + + inline QStyle *style() const { return m_style; } + inline QWidget *widget() const { return m_widget; } + + inline bool operator==(const QLayoutStyleInfo &other) + { return m_style == other.m_style && m_widget == other.m_widget; } + inline bool operator!=(const QLayoutStyleInfo &other) + { return !(*this == other); } + + inline void setDefaultSpacing(Qt::Orientation o, qreal spacing){ + if (spacing >= 0) + m_defaultSpacing[o - 1] = spacing; + } + + inline qreal defaultSpacing(Qt::Orientation o) const { + return m_defaultSpacing[o - 1]; + } + + inline qreal perItemSpacing(QSizePolicy::ControlType control1, + QSizePolicy::ControlType control2, + Qt::Orientation orientation) const + { + Q_ASSERT(style()); + return style()->layoutSpacing(control1, control2, orientation, &m_styleOption, widget()); + } +private: + bool m_valid; + QStyle *m_style; + QWidget *m_widget; + QStyleOption m_styleOption; + qreal m_defaultSpacing[2]; +}; + class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPrivate { Q_DECLARE_PUBLIC(QGraphicsLayout) diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp index 7ff7c9b..5684f0e 100644 --- a/src/gui/graphicsview/qgraphicslinearlayout.cpp +++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp @@ -59,7 +59,7 @@ You can add widgets, layouts, stretches (addStretch(), insertStretch() or setStretchFactor()), and spacings (setItemSpacing()) to a linear - layout. The layout takes ownership of the items. In some cases when the layout + layout. The layout takes ownership of the items. In some cases when the layout item also inherits from QGraphicsItem (such as QGraphicsWidget) there will be a ambiguity in ownership because the layout item belongs to two ownership hierarchies. See the documentation of QGraphicsLayoutItem::setOwnedByLayout() how to handle @@ -208,7 +208,7 @@ QGraphicsLinearLayout::~QGraphicsLinearLayout() for (int i = count() - 1; i >= 0; --i) { QGraphicsLayoutItem *item = itemAt(i); // The following lines can be removed, but this removes the item - // from the layout more efficiently than the implementation of + // from the layout more efficiently than the implementation of // ~QGraphicsLayoutItem. removeAt(i); if (item) { @@ -542,18 +542,18 @@ void QGraphicsLinearLayout::invalidate() QGraphicsLayout::invalidate(); } -#ifdef QT_DEBUG void QGraphicsLinearLayout::dump(int indent) const { +#ifdef QT_DEBUG if (qt_graphicsLayoutDebug()) { Q_D(const QGraphicsLinearLayout); qDebug("%*s%s layout", indent, "", d->orientation == Qt::Horizontal ? "Horizontal" : "Vertical"); d->engine.dump(indent + 1); } -} #endif +} QT_END_NAMESPACE - + #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslinearlayout.h b/src/gui/graphicsview/qgraphicslinearlayout.h index 742392e..15fe81a 100644 --- a/src/gui/graphicsview/qgraphicslinearlayout.h +++ b/src/gui/graphicsview/qgraphicslinearlayout.h @@ -97,9 +97,7 @@ public: Q5SizePolicy::ControlTypes controlTypes(LayoutSide side) const; #endif -#ifdef QT_DEBUG void dump(int indent = 0) const; -#endif protected: #if 0 diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index b7a3962..e9173a9 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -57,6 +57,9 @@ #include <QtGui/qpainter.h> #include <QtGui/qstyleoption.h> #include <QtGui/qgraphicsview.h> +#include <QtGui/qlistview.h> +#include <QtGui/qlineedit.h> +#include <QtGui/qtextedit.h> QT_BEGIN_NAMESPACE @@ -86,7 +89,9 @@ QT_BEGIN_NAMESPACE of embedded widgets through creating a child proxy for each popup. This means that when an embedded QComboBox shows its popup list, a new QGraphicsProxyWidget is created automatically, embedding the popup, and - positioning it correctly. + positioning it correctly. This only works if the popup is child of the + embedded widget (for example QToolButton::setMenu() requires the QMenu instance + to be child of the QToolButton). \section1 Embedding a Widget with QGraphicsProxyWidget @@ -184,6 +189,7 @@ QT_BEGIN_NAMESPACE */ extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); +extern bool qt_tab_all_widgets; /*! \internal @@ -369,6 +375,7 @@ QVariant QGraphicsProxyWidgetPrivate::inputMethodQueryHelper(Qt::InputMethodQuer /*! \internal + Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper */ QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const { @@ -382,14 +389,16 @@ QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) child = next ? child->d_func()->focus_next : child->d_func()->focus_prev; if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) { return 0; - } + } } QWidget *oldChild = child; + uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus; do { if (child->isEnabled() && child->isVisibleTo(widget) - && (child->focusPolicy() & Qt::TabFocus)) { + && ((child->focusPolicy() & focus_flag) == focus_flag) + && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) { return child; } child = next ? child->d_func()->focus_next : child->d_func()->focus_prev; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a624b10..f982f4b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -242,7 +242,6 @@ #include <QtGui/qstyleoption.h> #include <QtGui/qtooltip.h> #include <QtGui/qtransform.h> -#include <QtGui/qgesture.h> #include <QtGui/qinputcontext.h> #include <QtGui/qgraphicseffect.h> #include <private/qapplication_p.h> @@ -251,6 +250,14 @@ #include <private/qt_x11_p.h> #endif #include <private/qgraphicseffect_p.h> +#include <private/qgesturemanager_p.h> + +// #define GESTURE_DEBUG +#ifndef GESTURE_DEBUG +# define DEBUG if (0) qDebug +#else +# define DEBUG qDebug +#endif QT_BEGIN_NAMESPACE @@ -518,6 +525,14 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) item->d_func()->scene = 0; + //We need to remove all children first because they might use their parent + //attributes (e.g. sceneTransform). + if (!item->d_ptr->inDestructor) { + // Remove all children recursively + for (int i = 0; i < item->d_ptr->children.size(); ++i) + q->removeItem(item->d_ptr->children.at(i)); + } + // Unregister focus proxy. item->d_ptr->resetFocusProxy(); @@ -564,12 +579,6 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) ++iterator; } - if (!item->d_ptr->inDestructor) { - // Remove all children recursively - for (int i = 0; i < item->d_ptr->children.size(); ++i) - q->removeItem(item->d_ptr->children.at(i)); - } - if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) leaveModal(item); @@ -684,6 +693,7 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, focusItem = 0; sendEvent(lastFocusItem, &event); +#ifndef QT_NO_IM if (lastFocusItem && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { // Reset any visible preedit text @@ -699,6 +709,7 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, views.at(i)->inputContext()->reset(); } } +#endif //QT_NO_IM } if (item) { @@ -1052,6 +1063,14 @@ bool QGraphicsScenePrivate::filterEvent(QGraphicsItem *item, QEvent *event) */ bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event) { + if (QGraphicsObject *object = item->toGraphicsObject()) { + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + if (qAppPriv->gestureManager) { + if (qAppPriv->gestureManager->filterEvent(object, event)) + return true; + } + } + if (filterEvent(item, event)) return false; if (filterDescendantEvent(item, event)) @@ -3365,6 +3384,10 @@ bool QGraphicsScene::event(QEvent *event) case QEvent::TouchEnd: d->touchEventHandler(static_cast<QTouchEvent *>(event)); break; + case QEvent::Gesture: + case QEvent::GestureOverride: + d->gestureEventHandler(static_cast<QGestureEvent *>(event)); + break; default: return QObject::event(event); } @@ -4569,6 +4592,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * else painter->setWorldTransform(*transformPtr); painter->setOpacity(opacity); + + if (sourced->lastEffectTransform != painter->worldTransform()) { + sourced->lastEffectTransform = painter->worldTransform(); + sourced->invalidateCache(); + } item->d_ptr->graphicsEffect->draw(painter, source); painter->setWorldTransform(restoreTransform); sourced->info = 0; @@ -4886,7 +4914,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool continue; } - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint && !paintedViewBoundingRect.isEmpty()) { + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); if (!viewPrivate->updateRect(paintedViewBoundingRect)) paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. @@ -5699,6 +5727,238 @@ void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel) dispatchHoverEvent(&hoverEvent); } +void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures, + QWidget *viewport, + QMap<Qt::GestureType, QGesture *> *conflictedGestures, + QList<QList<QGraphicsObject *> > *conflictedItems, + QHash<QGesture *, QGraphicsObject *> *normalGestures) +{ + foreach (QGesture *gesture, gestures) { + Qt::GestureType gestureType = gesture->gestureType(); + if (gesture->hasHotSpot()) { + QPoint screenPos = gesture->hotSpot().toPoint(); + QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport); + QList<QGraphicsObject *> result; + for (int j = 0; j < items.size(); ++j) { + QGraphicsObject *item = items.at(j)->toGraphicsObject(); + if (!item) + continue; + QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); + if (d->gestureContext.contains(gestureType)) { + result.append(item); + } + } + DEBUG() << "QGraphicsScenePrivate::getGestureTargets:" + << gesture << result; + if (result.size() == 1) { + normalGestures->insert(gesture, result.first()); + } else if (!result.isEmpty()) { + conflictedGestures->insert(gestureType, gesture); + conflictedItems->append(result); + } + } + } +} + +void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) +{ + QWidget *viewport = event->widget(); + if (!viewport) + return; + QList<QGesture *> allGestures = event->allGestures(); + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "Delivering gestures:" << allGestures; + + typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem; + GesturesPerItem gesturesPerItem; + + QSet<QGesture *> startedGestures; + foreach (QGesture *gesture, allGestures) { + QGraphicsObject *target = gestureTargets.value(gesture, 0); + if (!target) { + // when we are not in started mode but don't have a target + // then the only one interested in gesture is the view/scene + if (gesture->state() == Qt::GestureStarted) + startedGestures.insert(gesture); + } else { + gesturesPerItem[target].append(gesture); + } + } + + QMap<Qt::GestureType, QGesture *> conflictedGestures; + QList<QList<QGraphicsObject *> > conflictedItems; + QHash<QGesture *, QGraphicsObject *> normalGestures; + getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems, + &normalGestures); + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "Conflicting gestures:" << conflictedGestures.values() << conflictedItems; + Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) || + (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty())); + + // gestures that were sent as override events, but no one accepted them + QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures; + + // deliver conflicted gestures as override events first + while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) { + // get the topmost item to deliver the override event + Q_ASSERT(!conflictedItems.isEmpty()); + Q_ASSERT(!conflictedItems.first().isEmpty()); + QGraphicsObject *topmost = conflictedItems.first().first(); + for (int i = 1; i < conflictedItems.size(); ++i) { + QGraphicsObject *item = conflictedItems.at(i).first(); + if (qt_closestItemFirst(item, topmost)) { + topmost = item; + } + } + // get a list of gestures to send to the item + QList<Qt::GestureType> grabbedGestures = + topmost->QGraphicsItem::d_func()->gestureContext.keys(); + QList<QGesture *> gestures; + for (int i = 0; i < grabbedGestures.size(); ++i) { + if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) { + gestures.append(g); + if (!ignoredConflictedGestures.contains(g)) + ignoredConflictedGestures.insert(g, topmost); + } + } + + // send gesture override to the topmost item + QGestureEvent ev(gestures); + ev.t = QEvent::GestureOverride; + ev.setWidget(event->widget()); + // mark event and individual gestures as ignored + ev.ignore(); + foreach(QGesture *g, gestures) + ev.setAccepted(g, false); + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "delivering override to" + << topmost << gestures; + sendEvent(topmost, &ev); + // mark all accepted gestures to deliver them as normal gesture events + foreach (QGesture *g, gestures) { + if (ev.isAccepted() || ev.isAccepted(g)) { + conflictedGestures.remove(g->gestureType()); + gestureTargets.remove(g); + // add the gesture to the list of normal delivered gestures + normalGestures.insert(g, topmost); + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "override was accepted:" + << g << topmost; + ignoredConflictedGestures.remove(g); + } + } + // remove the item that we've already delivered from the list + for (int i = 0; i < conflictedItems.size(); ) { + QList<QGraphicsObject *> &items = conflictedItems[i]; + if (items.first() == topmost) { + items.removeFirst(); + if (items.isEmpty()) { + conflictedItems.removeAt(i); + continue; + } + } + ++i; + } + } + + // put back those started gestures that are not in the conflicted state + // and remember their targets + QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(), + e = normalGestures.end(); + for (; it != e; ++it) { + QGesture *g = it.key(); + QGraphicsObject *receiver = it.value(); + Q_ASSERT(!gestureTargets.contains(g)); + gestureTargets.insert(g, receiver); + gesturesPerItem[receiver].append(g); + } + it = ignoredConflictedGestures.begin(); + e = ignoredConflictedGestures.end(); + for (; it != e; ++it) { + QGesture *g = it.key(); + QGraphicsObject *receiver = it.value(); + Q_ASSERT(!gestureTargets.contains(g)); + gestureTargets.insert(g, receiver); + gesturesPerItem[receiver].append(g); + } + + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "Started gestures:" << normalGestures.keys() + << "All gestures:" << gesturesPerItem.values(); + + // deliver all events + QList<QGesture *> alreadyIgnoredGestures; + QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures; + QList<QGraphicsObject *> targetItems = gesturesPerItem.keys(); + qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst); + for (int i = 0; i < targetItems.size(); ++i) { + QGraphicsObject *item = targetItems.at(i); + QList<QGesture *> gestures = gesturesPerItem.value(item); + // remove gestures that were already delivered once and were ignored + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "already ignored gestures for item" + << item << ":" << itemIgnoredGestures.value(item); + + if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item + continue; + + QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func(); + foreach(QGesture *g, alreadyIgnoredGestures) { + if (gid->gestureContext.contains(g->gestureType())) + gestures += g; + } + if (gestures.isEmpty()) + continue; + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "delivering to" + << item << gestures; + QGestureEvent ev(gestures); + ev.setWidget(event->widget()); + sendEvent(item, &ev); + QSet<QGesture *> ignoredGestures; + foreach (QGesture *g, gestures) { + if (!ev.isAccepted() && !ev.isAccepted(g)) + ignoredGestures.insert(g); + } + if (!ignoredGestures.isEmpty()) { + // get a list of items under the (current) hotspot of each ignored + // gesture and start delivery again from the beginning + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "item has ignored the event, will propagate." + << item << ignoredGestures; + itemIgnoredGestures[item] += ignoredGestures; + QMap<Qt::GestureType, QGesture *> conflictedGestures; + QList<QList<QGraphicsObject *> > itemsForConflictedGestures; + QHash<QGesture *, QGraphicsObject *> normalGestures; + getGestureTargets(ignoredGestures, viewport, + &conflictedGestures, &itemsForConflictedGestures, + &normalGestures); + QSet<QGraphicsObject *> itemsSet = targetItems.toSet(); + for (int k = 0; k < itemsForConflictedGestures.size(); ++k) + itemsSet += itemsForConflictedGestures.at(k).toSet(); + targetItems = itemsSet.toList(); + qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst); + alreadyIgnoredGestures = conflictedGestures.values(); + DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" + << "new targets:" << targetItems; + i = -1; // start delivery again + continue; + } + } + + // forget about targets for gestures that have ended + foreach (QGesture *g, allGestures) { + switch (g->state()) { + case Qt::GestureFinished: + case Qt::GestureCanceled: + gestureTargets.remove(g); + break; + default: + break; + } + } +} + QT_END_NAMESPACE #include "moc_qgraphicsscene.cpp" diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 8073695..cd20fd0 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -282,6 +282,13 @@ public: bool allItemsIgnoreTouchEvents; void enableTouchEventsOnViews(); + QHash<QGesture *, QGraphicsObject *> gestureTargets; + void gestureEventHandler(QGestureEvent *event); + void getGestureTargets(const QSet<QGesture *> &gestures, QWidget *viewport, + QMap<Qt::GestureType, QGesture *> *conflictedGestures, + QList<QList<QGraphicsObject *> > *conflictedItems, + QHash<QGesture *, QGraphicsObject *> *normalGestures); + void updateInputMethodSensitivityInViews(); QList<QGraphicsItem *> modalPanels; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index e21183a..47ae3f1 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -405,70 +405,6 @@ QList<QGraphicsItem *> QGraphicsSceneBspTreeIndexPrivate::estimateItems(const QR } /*! - Returns true if \a item1 is on top of \a item2. - - \internal -*/ -bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Siblings? Just check their z-values. - const QGraphicsItemPrivate *d1 = item1->d_ptr.data(); - const QGraphicsItemPrivate *d2 = item2->d_ptr.data(); - if (d1->parent == d2->parent) - return qt_closestLeaf(item1, item2); - - // Find common ancestor, and each item's ancestor closest to the common - // ancestor. - int item1Depth = d1->depth(); - int item2Depth = d2->depth(); - const QGraphicsItem *p = item1; - const QGraphicsItem *t1 = item1; - while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { - if (p == item2) { - // item2 is one of item1's ancestors; item1 is on top - return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t1 = p; - --item1Depth; - } - p = item2; - const QGraphicsItem *t2 = item2; - while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { - if (p == item1) { - // item1 is one of item2's ancestors; item1 is not on top - return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t2 = p; - --item2Depth; - } - - // item1Ancestor is now at the same level as item2Ancestor, but not the same. - const QGraphicsItem *a1 = t1; - const QGraphicsItem *a2 = t2; - while (a1) { - const QGraphicsItem *p1 = a1; - const QGraphicsItem *p2 = a2; - a1 = a1->parentItem(); - a2 = a2->parentItem(); - if (a1 && a1 == a2) - return qt_closestLeaf(p1, p2); - } - - // No common ancestor? Then just compare the items' toplevels directly. - return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); -} - -/*! - Returns true if \a item2 is on top of \a item1. - - \internal -*/ -bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return closestItemFirst_withoutCache(item2, item1); -} - -/*! Sort a list of \a itemList in a specific \a order and use the cache if requested. \internal @@ -495,9 +431,9 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList<QGraphicsItem *> *itemLi } } else { if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + qSort(itemList->begin(), itemList->end(), qt_closestItemFirst); } else if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + qSort(itemList->begin(), itemList->end(), qt_closestItemLast); } } } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 0a86bb7..c130190 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -145,8 +145,6 @@ public: QList<QGraphicsItem *> estimateItems(const QRectF &, Qt::SortOrder, bool b = false); static void climbTree(QGraphicsItem *item, int *stackingOrder); - static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) { diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp index ec1a2f5..83bc9e1 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -69,6 +69,9 @@ objects are applied to a QGraphicsItem, all of the transformations are computed in true 3D space, with the projection back to 2D only occurring after the last QGraphicsTransform is applied. + The exception to this is QGraphicsRotation, which projects back to + 2D after each rotation to preserve the perspective effect around + the X and Y axes. If you want to create your own configurable transformation, you can create a subclass of QGraphicsTransform (or any or the existing subclasses), and @@ -90,8 +93,8 @@ #include <QDebug> #include <QtCore/qmath.h> +#ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE - void QGraphicsTransformPrivate::setItem(QGraphicsItem *i) { if (item == i) @@ -547,7 +550,7 @@ void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const return; matrix->translate(d->origin); - matrix->rotate(d->angle, d->axis.x(), d->axis.y(), d->axis.z()); + matrix->projectedRotate(d->angle, d->axis.x(), d->axis.y(), d->axis.z()); matrix->translate(-d->origin); } @@ -562,3 +565,4 @@ void QGraphicsRotation::applyTo(QMatrix4x4 *matrix) const #include "moc_qgraphicstransform.cpp" QT_END_NAMESPACE +#endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h index 58075aa..58e3077 100644 --- a/src/gui/graphicsview/qgraphicstransform.h +++ b/src/gui/graphicsview/qgraphicstransform.h @@ -47,6 +47,7 @@ #include <QtGui/QTransform> #include <QtGui/QMatrix4x4> +#ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -150,5 +151,6 @@ private: QT_END_NAMESPACE QT_END_HEADER +#endif //QT_NO_GRAPHICSVIEW #endif // QFXTRANSFORM_H diff --git a/src/gui/graphicsview/qgraphicstransform_p.h b/src/gui/graphicsview/qgraphicstransform_p.h index 9e708b2..ddf99bb 100644 --- a/src/gui/graphicsview/qgraphicstransform_p.h +++ b/src/gui/graphicsview/qgraphicstransform_p.h @@ -54,7 +54,7 @@ // #include "private/qobject_p.h" - +#ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE class QGraphicsItem; @@ -73,5 +73,6 @@ public: }; QT_END_NAMESPACE +#endif //QT_NO_GRAPHCISVIEW #endif // QGRAPHICSTRANSFORM_P_H diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 32747cc..c88f678 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -281,6 +281,7 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < #include <QtGui/qstyleoption.h> #include <QtGui/qinputcontext.h> #ifdef Q_WS_X11 +#include <QtGui/qpaintengine.h> #include <private/qt_x11_p.h> #endif @@ -2701,6 +2702,19 @@ bool QGraphicsView::viewportEvent(QEvent *event) return true; } + case QEvent::Gesture: + case QEvent::GestureOverride: + { + if (!isEnabled()) + return false; + + if (d->scene && d->sceneInteractionAllowed) { + QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event); + gestureEvent->setWidget(viewport()); + (void) QApplication::sendEvent(d->scene, gestureEvent); + } + return true; + } default: break; } @@ -3281,7 +3295,12 @@ void QGraphicsView::paintEvent(QPaintEvent *event) backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); if (viewTransformed) backgroundPainter.setTransform(viewTransform); - backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); +#ifdef Q_WS_X11 +#undef X11 + if (backgroundPainter.paintEngine()->type() != QPaintEngine::X11) +#define X11 qt_x11Data +#endif + backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); drawBackground(&backgroundPainter, exposedSceneRect); d->backgroundPixmapExposed = QRegion(); } @@ -3306,6 +3325,14 @@ void QGraphicsView::paintEvent(QPaintEvent *event) if (!(d->optimizationFlags & IndirectPainting)) { d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0, &d->exposedRegion, viewport()); + // Make sure the painter's world transform is restored correctly when + // drawing without painter state protection (DontSavePainterState). + // We only change the worldTransform() so there's no need to do a full-blown + // save() and restore(). Also note that we don't have to do this in case of + // IndirectPainting (the else branch), because in that case we always save() + // and restore() in QGraphicsScene::drawItems(). + if (!d->scene->d_func()->painterStateProtection) + painter.setWorldTransform(viewTransform); } else { // Find all exposed items bool allItems = false; diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 35a3c13..d70a281 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -1352,6 +1352,8 @@ void QGraphicsWidget::changeEvent(QEvent *event) case QEvent::StyleChange: // ### Don't unset if the margins are explicitly set. unsetWindowFrameMargins(); + if (d->layout) + d->layout->invalidate(); case QEvent::FontChange: update(); updateGeometry(); diff --git a/src/gui/graphicsview/qgridlayoutengine_p.h b/src/gui/graphicsview/qgridlayoutengine_p.h index a42a537..ed335a8 100644 --- a/src/gui/graphicsview/qgridlayoutengine_p.h +++ b/src/gui/graphicsview/qgridlayoutengine_p.h @@ -59,7 +59,7 @@ #include "qmap.h" #include "qpair.h" #include "qvector.h" - +#include "qgraphicslayout_p.h" #include <float.h> QT_BEGIN_NAMESPACE @@ -128,29 +128,6 @@ public: }; -class QLayoutStyleInfo -{ -public: - inline QLayoutStyleInfo() { invalidate(); } - inline QLayoutStyleInfo(QStyle *style, QWidget *widget) - : q_valid(true), q_style(style), q_widget(widget) {} - - inline void invalidate() { q_valid = false; q_style = 0; q_widget = 0; } - - inline QStyle *style() const { return q_style; } - inline QWidget *widget() const { return q_widget; } - - inline bool operator==(const QLayoutStyleInfo &other) - { return q_style == other.q_style && q_widget == other.q_widget; } - inline bool operator!=(const QLayoutStyleInfo &other) - { return !(*this == other); } - -private: - bool q_valid; - QStyle *q_style; - QWidget *q_widget; -}; - class QGridLayoutBox { public: diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp index b8f8fb4..86b10b4 100644 --- a/src/gui/graphicsview/qsimplex_p.cpp +++ b/src/gui/graphicsview/qsimplex_p.cpp @@ -108,10 +108,8 @@ void QSimplex::clearDataStructures() // Constraints for (int i = 0; i < constraints.size(); ++i) { delete constraints[i]->helper.first; - constraints[i]->helper.first = 0; - constraints[i]->helper.second = 0.0; delete constraints[i]->artificial; - constraints[i]->artificial = 0; + delete constraints[i]; } constraints.clear(); @@ -137,7 +135,23 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) if (newConstraints.isEmpty()) return true; // we are ok with no constraints - constraints = newConstraints; + + // Make deep copy of constraints. We need this copy because we may change + // them in the simplification method. + for (int i = 0; i < newConstraints.size(); ++i) { + QSimplexConstraint *c = new QSimplexConstraint; + c->constant = newConstraints[i]->constant; + c->ratio = newConstraints[i]->ratio; + c->variables = newConstraints[i]->variables; + constraints << c; + } + + // Remove constraints of type Var == K and replace them for their value. + if (!simplifyConstraints(&constraints)) { + qWarning() << "QSimplex: No feasible solution!"; + clearDataStructures(); + return false; + } /////////////////////////////////////// // Prepare variables and constraints // @@ -508,11 +522,21 @@ qreal QSimplex::solver(solverFactor factor) // Remove old objective clearRow(0); - // Set new objective + // Set new objective in the first row of the simplex matrix + qreal resultOffset = 0; QHash<QSimplexVariable *, qreal>::const_iterator iter; for (iter = objective->variables.constBegin(); iter != objective->variables.constEnd(); ++iter) { + + // Check if the variable was removed in the simplification process. + // If so, we save its offset to the objective function and skip adding + // it to the matrix. + if (iter.key()->index == -1) { + resultOffset += iter.value() * iter.key()->result; + continue; + } + setValueAt(0, iter.key()->index, -1 * factor * iter.value()); } @@ -525,7 +549,9 @@ qreal QSimplex::solver(solverFactor factor) } #endif - return factor * valueAt(0, columns - 1); + // Return the value calculated by the simplex plus the value of the + // fixed variables. + return (factor * valueAt(0, columns - 1)) + resultOffset; } /*! @@ -571,4 +597,77 @@ void QSimplex::collectResults() } } +/*! + \internal + + Looks for single-valued variables and remove them from the constraints list. +*/ +bool QSimplex::simplifyConstraints(QList<QSimplexConstraint *> *constraints) +{ + QHash<QSimplexVariable *, qreal> results; // List of single-valued variables + bool modified = true; // Any chance more optimization exists? + + while (modified) { + modified = false; + + // For all constraints + QList<QSimplexConstraint *>::iterator iter = constraints->begin(); + while (iter != constraints->end()) { + QSimplexConstraint *c = *iter; + if ((c->ratio == QSimplexConstraint::Equal) && (c->variables.count() == 1)) { + // Check whether this is a constraint of type Var == K + // If so, save its value to "results". + QSimplexVariable *variable = c->variables.constBegin().key(); + qreal result = c->constant / c->variables.value(variable); + + results.insert(variable, result); + variable->result = result; + variable->index = -1; + modified = true; + + } + + // Replace known values among their variables + QHash<QSimplexVariable *, qreal>::const_iterator r; + for (r = results.constBegin(); r != results.constEnd(); ++r) { + if (c->variables.contains(r.key())) { + c->constant -= r.value() * c->variables.take(r.key()); + modified = true; + } + } + + // Keep it normalized + if (c->constant < 0) + c->invert(); + + if (c->variables.isEmpty()) { + // If constraint became empty due to substitution, delete it. + if (c->isSatisfied() == false) + // We must ensure that the constraint soon to be deleted would not + // make the problem unfeasible if left behind. If that's the case, + // we return false so the simplex solver can properly report that. + return false; + + delete c; + iter = constraints->erase(iter); + } else { + ++iter; + } + } + } + + return true; +} + +void QSimplexConstraint::invert() +{ + constant = -constant; + ratio = Ratio(2 - ratio); + + QHash<QSimplexVariable *, qreal>::iterator iter; + for (iter = variables.begin(); iter != variables.end(); ++iter) { + iter.value() = -iter.value(); + } +} + QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qsimplex_p.h b/src/gui/graphicsview/qsimplex_p.h index 51991a9..084ad7f 100644 --- a/src/gui/graphicsview/qsimplex_p.h +++ b/src/gui/graphicsview/qsimplex_p.h @@ -63,7 +63,7 @@ struct QSimplexVariable QSimplexVariable() : result(0), index(0) {} qreal result; - uint index; + int index; }; @@ -95,7 +95,8 @@ struct QSimplexConstraint QPair<QSimplexVariable *, qreal> helper; QSimplexVariable * artificial; -#ifdef QT_DEBUG + void invert(); + bool isSatisfied() { qreal leftHandSide(0); @@ -106,7 +107,7 @@ struct QSimplexConstraint Q_ASSERT(constant > 0 || qFuzzyCompare(1, 1 + constant)); - if (qFuzzyCompare(1000 + leftHandSide, 1000 + constant)) + if ((leftHandSide == constant) || qFuzzyCompare(1000 + leftHandSide, 1000 + constant)) return true; switch (ratio) { @@ -118,6 +119,30 @@ struct QSimplexConstraint return false; } } + +#ifdef QT_DEBUG + QString toString() { + QString result; + result += QString::fromAscii("-- QSimplexConstraint %1 --").arg(quintptr(this), 0, 16); + + QHash<QSimplexVariable *, qreal>::const_iterator iter; + for (iter = variables.constBegin(); iter != variables.constEnd(); ++iter) { + result += QString::fromAscii(" %1 x %2").arg(iter.value()).arg(quintptr(iter.key()), 0, 16); + } + + switch (ratio) { + case LessOrEqual: + result += QString::fromAscii(" (less) <= %1").arg(constant); + break; + case MoreOrEqual: + result += QString::fromAscii(" (more) >= %1").arg(constant); + break; + default: + result += QString::fromAscii(" (eqal) == %1").arg(constant); + } + + return result; + } #endif }; @@ -129,7 +154,6 @@ public: qreal solveMin(); qreal solveMax(); - QList<QSimplexVariable *> constraintsVariables(); bool setConstraints(const QList<QSimplexConstraint *> constraints); void setObjective(QSimplexConstraint *objective); @@ -145,6 +169,7 @@ private: void combineRows(int toIndex, int fromIndex, qreal factor); // Simplex + bool simplifyConstraints(QList<QSimplexConstraint *> *constraints); int findPivotColumn(); int pivotRowForColumn(int column); void reducedRowEchelon(); @@ -168,11 +193,6 @@ private: qreal *matrix; }; -inline QList<QSimplexVariable *> QSimplex::constraintsVariables() -{ - return variables; -} - inline qreal QSimplex::valueAt(int rowIndex, int columnIndex) { return matrix[rowIndex * columns + columnIndex]; diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index e0779a0..cff9cd2 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -66,6 +66,7 @@ #include "private/qkde_p.h" #endif +#ifndef QT_NO_ICON QT_BEGIN_NAMESPACE /*! @@ -1217,3 +1218,4 @@ QSize QIcon::pixmapSize(Size which) */ QT_END_NAMESPACE +#endif //QT_NO_ICON diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index fc96a65..43a59a6 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -60,6 +60,7 @@ #include <QtGui/qicon.h> #include <QtGui/qiconengine.h> +#ifndef QT_NO_ICON QT_BEGIN_NAMESPACE class QIconPrivate @@ -134,5 +135,5 @@ private: }; QT_END_NAMESPACE - +#endif //QT_NO_ICON #endif // QICON_P_H diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 46c5431..15af7a2 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -38,7 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - +#ifndef QT_NO_ICON #include <private/qiconloader_p.h> #include <private/qapplication_p.h> @@ -61,7 +61,6 @@ #ifdef Q_WS_X11 #include <private/qt_x11_p.h> -#include <private/gtksymbols_p.h> #endif QT_BEGIN_NAMESPACE @@ -92,11 +91,13 @@ QIconLoader::QIconLoader() : if (m_systemTheme.isEmpty()) m_systemTheme = fallbackTheme(); +#ifndef QT_NO_LIBRARY QFactoryLoader iconFactoryLoader(QIconEngineFactoryInterfaceV2_iid, QLatin1String("/iconengines"), Qt::CaseInsensitive); if (iconFactoryLoader.keys().contains(QLatin1String("svg"))) m_supportsSvg = true; +#endif //QT_NO_LIBRARY } QIconLoader *QIconLoader::instance() @@ -160,7 +161,7 @@ QIconTheme::QIconTheme(const QString &themeName) break; } } - +#ifndef QT_NO_SETTINGS if (themeIndex.exists()) { const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat); QStringListIterator keyIterator(indexReader.allKeys()); @@ -213,6 +214,7 @@ QIconTheme::QIconTheme(const QString &themeName) if (!m_parents.contains(QLatin1String("hicolor"))) m_parents.append(QLatin1String("hicolor")); } +#endif //QT_NO_SETTINGS } QThemeIconEntries QIconLoader::findIconHelper(const QString &themeName, @@ -546,3 +548,5 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) } QT_END_NAMESPACE + +#endif //QT_NO_ICON diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h index b152d46..2a330d3 100644 --- a/src/gui/image/qiconloader_p.h +++ b/src/gui/image/qiconloader_p.h @@ -42,6 +42,7 @@ #ifndef QDESKTOPICON_P_H #define QDESKTOPICON_P_H +#ifndef QT_NO_ICON // // W A R N I N G // ------------- @@ -185,3 +186,5 @@ private: QT_END_NAMESPACE #endif // QDESKTOPICON_P_H + +#endif //QT_NO_ICON diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 21ab40c..571ef9d 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -546,11 +546,7 @@ bool QImageData::checkForAlphaPixels() const Each pixel stored in a QImage is represented by an integer. The size of the integer varies depending on the format. QImage supports several image formats described by the \l Format - enum. The monochrome (1-bit), 8-bit and 32-bit images are - available in all versions of Qt. In addition Qt for Embedded Linux - also supports 2-bit, 4-bit, and 16-bit images. For more information - about the Qt Extended specific formats, see the documentation of the \l - Format enum. + enum. Monochrome images are stored using 1-bit indexes into a color table with at most two colors. There are two different types of @@ -707,9 +703,20 @@ bool QImageData::checkForAlphaPixels() const packed with the most significant bit (MSB) first. \value Format_MonoLSB The image is stored using 1-bit per pixel. Bytes are packed with the less significant bit (LSB) first. - \value Format_Indexed8 The image is stored using 8-bit indexes into a colormap. + + \value Format_Indexed8 The image is stored using 8-bit indexes + into a colormap. \warning Drawing into a + QImage with Indexed8 format is not + supported. + \value Format_RGB32 The image is stored using a 32-bit RGB format (0xffRRGGBB). - \value Format_ARGB32 The image is stored using a 32-bit ARGB format (0xAARRGGBB). + + \value Format_ARGB32 The image is stored using a 32-bit ARGB + format (0xAARRGGBB). \warning Do not + render into ARGB32 images using + QPainter. Format_ARGB32_Premultiplied is + significantly faster. + \value Format_ARGB32_Premultiplied The image is stored using a premultiplied 32-bit ARGB format (0xAARRGGBB), i.e. the red, green, and blue channels are multiplied @@ -718,7 +725,9 @@ bool QImageData::checkForAlphaPixels() const undefined.) Certain operations (such as image composition using alpha blending) are faster using premultiplied ARGB32 than with plain ARGB32. + \value Format_RGB16 The image is stored using a 16-bit RGB format (5-6-5). + \value Format_ARGB8565_Premultiplied The image is stored using a premultiplied 24-bit ARGB format (8-5-6-5). \value Format_RGB666 The image is stored using a 24-bit RGB format (6-6-6). diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp index ac30646..35322e9 100644 --- a/src/gui/image/qimagepixmapcleanuphooks.cpp +++ b/src/gui/image/qimagepixmapcleanuphooks.cpp @@ -40,7 +40,8 @@ ****************************************************************************/ #include "qimagepixmapcleanuphooks_p.h" -#include "qpixmapdata_p.h" +#include "private/qpixmapdata_p.h" +#include "private/qimage_p.h" QT_BEGIN_NAMESPACE @@ -132,4 +133,19 @@ void QImagePixmapCleanupHooks::executeImageHooks(qint64 key) qt_image_cleanup_hook_64(key); } +void QImagePixmapCleanupHooks::enableCleanupHooks(const QPixmap &pixmap) +{ + enableCleanupHooks(const_cast<QPixmap &>(pixmap).data_ptr().data()); +} + +void QImagePixmapCleanupHooks::enableCleanupHooks(QPixmapData *pixmapData) +{ + pixmapData->is_cached = true; +} + +void QImagePixmapCleanupHooks::enableCleanupHooks(const QImage &image) +{ + const_cast<QImage &>(image).data_ptr()->is_cached = true; +} + QT_END_NAMESPACE diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h index 16c8974..9e490d7 100644 --- a/src/gui/image/qimagepixmapcleanuphooks_p.h +++ b/src/gui/image/qimagepixmapcleanuphooks_p.h @@ -70,6 +70,10 @@ public: static QImagePixmapCleanupHooks *instance(); + static void enableCleanupHooks(const QImage &image); + static void enableCleanupHooks(const QPixmap &pixmap); + static void enableCleanupHooks(QPixmapData *pixmapData); + // Gets called when a pixmap is about to be modified: void addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm); diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index 88faea8..e4ea2e9 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -199,10 +199,12 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* shmctl(xshminfo.shmid, IPC_RMID, 0); return; } - xshmpm = XShmCreatePixmap(X11->display, DefaultRootWindow(X11->display), xshmimg->data, - &xshminfo, width, height, dd); - if (!xshmpm) { - qWarning() << "QNativeImage: Unable to create shared Pixmap."; + if (X11->use_mitshm_pixmaps) { + xshmpm = XShmCreatePixmap(X11->display, DefaultRootWindow(X11->display), xshmimg->data, + &xshminfo, width, height, dd); + if (!xshmpm) { + qWarning() << "QNativeImage: Unable to create shared Pixmap."; + } } } diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index f94552d..c452b9a 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -113,13 +113,10 @@ void QPixmap::init(int w, int h, Type type) void QPixmap::init(int w, int h, int type) { - QGraphicsSystem* gs = QApplicationPrivate::graphicsSystem(); - if (gs) - data = gs->createPixmapData(static_cast<QPixmapData::PixelType>(type)); + if ((w > 0 && h > 0) || type == QPixmapData::BitmapType) + data = QPixmapData::create(w, h, (QPixmapData::PixelType) type); else - data = QGraphicsSystem::createDefaultPixmapData(static_cast<QPixmapData::PixelType>(type)); - - data->resize(w, h); + data = 0; } /*! @@ -307,7 +304,7 @@ QPixmap::QPixmap(const char * const xpm[]) QImage image(xpm); if (!image.isNull()) { - if (data->pixelType() == QPixmapData::BitmapType) + if (data && data->pixelType() == QPixmapData::BitmapType) *this = QBitmap::fromImage(image); else *this = fromImage(image); @@ -322,8 +319,8 @@ QPixmap::QPixmap(const char * const xpm[]) QPixmap::~QPixmap() { - Q_ASSERT(data->ref >= 1); // Catch if ref-counting changes again - if (data->is_cached && data->ref == 1) // ref will be decrememnted after destructor returns + Q_ASSERT(!data || data->ref >= 1); // Catch if ref-counting changes again + if (data && data->is_cached && data->ref == 1) // ref will be decrememnted after destructor returns QImagePixmapCleanupHooks::executePixmapDestructionHooks(this); } @@ -470,9 +467,11 @@ QPixmap::operator QVariant() const conversion fails. If the pixmap has 1-bit depth, the returned image will also be 1 - bit deep. If the pixmap has 2- to 8-bit depth, the returned image - has 8-bit depth. If the pixmap has greater than 8-bit depth, the - returned image has 32-bit depth. + bit deep. Images with more bits will be returned in a format + closely represents the underlying system. Usually this will be + QImage::Format_ARGB32_Premultiplied for pixmaps with an alpha and + QImage::Format_RGB32 or QImage::Format_RGB16 for pixmaps without + alpha. Note that for the moment, alpha masks on monochrome images are ignored. @@ -542,7 +541,7 @@ bool QPixmap::isQBitmap() const */ bool QPixmap::isNull() const { - return data->isNull(); + return !data || data->isNull(); } /*! @@ -554,7 +553,7 @@ bool QPixmap::isNull() const */ int QPixmap::width() const { - return data->width(); + return data ? data->width() : 0; } /*! @@ -566,7 +565,7 @@ int QPixmap::width() const */ int QPixmap::height() const { - return data->height(); + return data ? data->height() : 0; } /*! @@ -579,7 +578,7 @@ int QPixmap::height() const */ QSize QPixmap::size() const { - return QSize(data->width(), data->height()); + return data ? QSize(data->width(), data->height()) : QSize(); } /*! @@ -591,7 +590,7 @@ QSize QPixmap::size() const */ QRect QPixmap::rect() const { - return QRect(0, 0, data->width(), data->height()); + return data ? QRect(0, 0, data->width(), data->height()) : QRect(); } /*! @@ -607,7 +606,7 @@ QRect QPixmap::rect() const */ int QPixmap::depth() const { - return data->depth(); + return data ? data->depth() : 0; } /*! @@ -637,7 +636,7 @@ void QPixmap::resize_helper(const QSize &s) return; // Create new pixmap - QPixmap pm(QSize(w, h), data->type); + QPixmap pm(QSize(w, h), data ? data->type : QPixmapData::PixmapType); bool uninit = false; #if defined(Q_WS_X11) QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data.data()) : 0; @@ -726,6 +725,9 @@ void QPixmap::setMask(const QBitmap &mask) return; } + if (isNull()) + return; + if (static_cast<const QPixmap &>(mask).data == data) // trying to selfmask return; @@ -824,11 +826,14 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers QFileInfo info(fileName); QString key = QLatin1String("qt_pixmap_") + info.absoluteFilePath() + QLatin1Char('_') + QString::number(info.lastModified().toTime_t()) + QLatin1Char('_') + - QString::number(info.size()) + QLatin1Char('_') + QString::number(data->pixelType()); + QString::number(info.size()) + QLatin1Char('_') + QString::number(data ? data->pixelType() : QPixmapData::PixmapType); if (QPixmapCache::find(key, *this)) return true; + if (!data) + data = QPixmapData::create(0, 0, QPixmapData::PixmapType); + if (data->fromFile(fileName, format, flags)) { QPixmapCache::insert(key, *this); return true; @@ -858,6 +863,12 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers bool QPixmap::loadFromData(const uchar *buf, uint len, const char *format, Qt::ImageConversionFlags flags) { + if (len == 0 || buf == 0) + return false; + + if (!data) + data = QPixmapData::create(0, 0, QPixmapData::PixmapType); + return data->fromData(buf, len, format, flags); } @@ -1003,6 +1014,9 @@ int QPixmap::serialNumber() const */ qint64 QPixmap::cacheKey() const { + if (isNull()) + return 0; + int classKey = data->classId(); if (classKey >= 1024) classKey = -(classKey >> 10); @@ -1219,7 +1233,7 @@ QPixmap::QPixmap(const QImage& image) QPixmap &QPixmap::operator=(const QImage &image) { - if (data->pixelType() == QPixmapData::BitmapType) + if (data && data->pixelType() == QPixmapData::BitmapType) *this = QBitmap::fromImage(image); else *this = fromImage(image); @@ -1249,7 +1263,7 @@ bool QPixmap::loadFromData(const uchar *buf, uint len, const char *format, Color */ bool QPixmap::convertFromImage(const QImage &image, ColorMode mode) { - if (data->pixelType() == QPixmapData::BitmapType) + if (data && data->pixelType() == QPixmapData::BitmapType) *this = QBitmap::fromImage(image, colorModeToFlags(mode)); else *this = fromImage(image, colorModeToFlags(mode)); @@ -1336,7 +1350,7 @@ Q_GUI_EXPORT void copyBlt(QPixmap *dst, int dx, int dy, bool QPixmap::isDetached() const { - return data->ref == 1; + return data && data->ref == 1; } /*! \internal @@ -1704,8 +1718,8 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) In addition, on Symbian, the QPixmap class supports conversion to and from CFbsBitmap: the toSymbianCFbsBitmap() function creates - CFbsBitmap equivalent to the QPixmap, based on given mode and returns - a CFbsBitmap object. The fromSymbianCFbsBitmap() function returns a + CFbsBitmap equivalent to the QPixmap, based on given mode and returns + a CFbsBitmap object. The fromSymbianCFbsBitmap() function returns a QPixmap that is equivalent to the given bitmap and given mode. \section1 Pixmap Transformations @@ -1748,7 +1762,7 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) */ bool QPixmap::hasAlpha() const { - return (data->hasAlphaChannel() || !data->mask().isNull()); + return data && (data->hasAlphaChannel() || !data->mask().isNull()); } /*! @@ -1759,7 +1773,7 @@ bool QPixmap::hasAlpha() const */ bool QPixmap::hasAlphaChannel() const { - return data->hasAlphaChannel(); + return data && data->hasAlphaChannel(); } /*! @@ -1767,7 +1781,7 @@ bool QPixmap::hasAlphaChannel() const */ int QPixmap::metric(PaintDeviceMetric metric) const { - return data->metric(metric); + return data ? data->metric(metric) : 0; } /*! @@ -1839,7 +1853,7 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel) */ QPixmap QPixmap::alphaChannel() const { - return data->alphaChannel(); + return data ? data->alphaChannel() : QPixmap(); } /*! @@ -1847,7 +1861,7 @@ QPixmap QPixmap::alphaChannel() const */ QPaintEngine *QPixmap::paintEngine() const { - return data->paintEngine(); + return data ? data->paintEngine() : 0; } /*! @@ -1862,7 +1876,7 @@ QPaintEngine *QPixmap::paintEngine() const */ QBitmap QPixmap::mask() const { - return data->mask(); + return data ? data->mask() : QBitmap(); } /*! @@ -1911,6 +1925,9 @@ int QPixmap::defaultDepth() */ void QPixmap::detach() { + if (!data) + return; + QPixmapData::ClassId id = data->classId(); if (id == QPixmapData::RasterClass) { QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data.data()); diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp index afa6f83..9209d45 100644 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -305,11 +305,15 @@ void QMacPixmapData::fromImage(const QImage &img, } break; } - case QImage::Format_Indexed8: - for (int x = 0; x < w; ++x) { - *(drow+x) = PREMUL(image.color(*(srow + x))); + case QImage::Format_Indexed8: { + int numColors = image.numColors(); + if (numColors > 0) { + for (int x = 0; x < w; ++x) { + int index = *(srow + x); + *(drow+x) = PREMUL(image.color(qMin(index, numColors))); + } } - break; + } break; case QImage::Format_RGB32: for (int x = 0; x < w; ++x) *(drow+x) = *(((quint32*)srow) + x) | 0xFF000000; @@ -965,6 +969,9 @@ Qt::HANDLE QPixmap::macQDAlphaHandle() const Qt::HANDLE QPixmap::macCGHandle() const { + if (isNull()) + return 0; + if (data->classId() == QPixmapData::MacClass) { QMacPixmapData *d = static_cast<QMacPixmapData *>(data.data()); if (!d->cg_data) diff --git a/src/gui/image/qpixmap_qws.cpp b/src/gui/image/qpixmap_qws.cpp index 6b4283e..a8516a5 100644 --- a/src/gui/image/qpixmap_qws.cpp +++ b/src/gui/image/qpixmap_qws.cpp @@ -114,7 +114,7 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) QRgb* QPixmap::clut() const { - if (data->classId() == QPixmapData::RasterClass) { + if (data && data->classId() == QPixmapData::RasterClass) { const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data()); return d->image.colorTable().data(); } @@ -124,7 +124,7 @@ QRgb* QPixmap::clut() const int QPixmap::numCols() const { - if (data->classId() == QPixmapData::RasterClass) { + if (data && data->classId() == QPixmapData::RasterClass) { const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data()); return d->image.numColors(); } @@ -134,7 +134,7 @@ int QPixmap::numCols() const const uchar* QPixmap::qwsBits() const { - if (data->classId() == QPixmapData::RasterClass) { + if (data && data->classId() == QPixmapData::RasterClass) { const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data()); return d->image.bits(); } @@ -144,7 +144,7 @@ const uchar* QPixmap::qwsBits() const int QPixmap::qwsBytesPerLine() const { - if (data->classId() == QPixmapData::RasterClass) { + if (data && data->classId() == QPixmapData::RasterClass) { const QRasterPixmapData *d = static_cast<const QRasterPixmapData*>(data.data()); return d->image.bytesPerLine(); } diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index 666d608..7f0a504 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -311,7 +311,7 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h) CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const { QPixmapData *data = pixmapData(); - if (data->isNull()) + if (!data || data->isNull()) return 0; return reinterpret_cast<CFbsBitmap*>(data->toNativeType(QPixmapData::FbsBitmap)); @@ -337,8 +337,9 @@ QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap) if (!bitmap) return QPixmap(); - QPixmap pixmap; - pixmap.pixmapData()->fromNativeType(reinterpret_cast<void*>(bitmap), QPixmapData::FbsBitmap); + QScopedPointer<QS60PixmapData> data(new QS60PixmapData(QPixmapData::PixmapType)); + data->fromNativeType(reinterpret_cast<void*>(bitmap), QPixmapData::FbsBitmap); + QPixmap pixmap(data.take()); return pixmap; } @@ -684,9 +685,10 @@ void QS60PixmapData::beginDataAccess() uchar* newBytes = (uchar*)cfbsBitmap->DataAddress(); - if (newBytes == bytes) - return; + TSize size = cfbsBitmap->SizeInPixels(); + if (newBytes == bytes && image.width() == size.iWidth && image.height() == size.iHeight) + return; bytes = newBytes; TDisplayMode mode = cfbsBitmap->DisplayMode(); @@ -695,8 +697,6 @@ void QS60PixmapData::beginDataAccess() if (format == QImage::Format_ARGB32) format = QImage::Format_ARGB32_Premultiplied; // pixel data is actually in premultiplied format - TSize size = cfbsBitmap->SizeInPixels(); - QVector<QRgb> savedColorTable; if (!image.isNull()) savedColorTable = image.colorTable(); @@ -752,9 +752,9 @@ QPixmap QPixmap::fromSymbianRSgImage(RSgImage *sgImage) if (!sgImage) return QPixmap(); - QPixmap pixmap; - pixmap.pixmapData()->fromNativeType(reinterpret_cast<void*>(sgImage), QPixmapData::SgImage); - + QScopedPointer<QS60PixmapData> data(new QS60PixmapData(QPixmapData::PixmapType)); + data->fromNativeType(reinterpret_cast<void*>(bitmap), QPixmapData::SgImage); + QPixmap pixmap(data.take()); return pixmap; } @@ -935,18 +935,21 @@ void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType) da.beginDataAccess(sourceBitmap); uchar *bytes = (uchar*)sourceBitmap->DataAddress(); QImage img = QImage(bytes, size.iWidth, size.iHeight, format); + img = img.copy(); da.endDataAccess(sourceBitmap); - fromImage(img, Qt::AutoColor); - - if(deleteSourceBitmap) - delete sourceBitmap; - if(displayMode == EGray2) { //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid //So invert mono bitmaps so that masks work correctly. - image.invertPixels(); + img.invertPixels(); + } else if(displayMode == EColor16M) { + img = img.rgbSwapped(); // EColor16M is BGR } + + fromImage(img, Qt::AutoColor); + + if(deleteSourceBitmap) + delete sourceBitmap; } else { CFbsBitmap* duplicate = 0; QT_TRAP_THROWING(duplicate = new (ELeave) CFbsBitmap); diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 1b61484..04027c1 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -121,6 +121,9 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h ) HBITMAP QPixmap::toWinHBITMAP(HBitmapFormat format) const { + if (isNull()) + return 0; + HBITMAP bitmap = 0; if (data->classId() == QPixmapData::RasterClass) { QRasterPixmapData* d = static_cast<QRasterPixmapData*>(data.data()); diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index ea9eff9..8a0120a 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -1976,6 +1976,9 @@ void QPixmap::x11SetScreen(int screen) return; } + if (isNull()) + return; + if (data->classId() != QPixmapData::X11Class) return; @@ -2078,7 +2081,7 @@ bool QX11PixmapData::hasAlphaChannel() const const QX11Info &QPixmap::x11Info() const { - if (data->classId() == QPixmapData::X11Class) + if (data && data->classId() == QPixmapData::X11Class) return static_cast<QX11PixmapData*>(data.data())->xinfo; else { static QX11Info nullX11Info; @@ -2135,7 +2138,7 @@ QPaintEngine* QX11PixmapData::paintEngine() const Qt::HANDLE QPixmap::x11PictureHandle() const { #ifndef QT_NO_XRENDER - if (data->classId() == QPixmapData::X11Class) + if (data && data->classId() == QPixmapData::X11Class) return static_cast<const QX11PixmapData*>(data.data())->picture; else return 0; diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp index 1ad1f02..10194e4 100644 --- a/src/gui/image/qpixmapdata.cpp +++ b/src/gui/image/qpixmapdata.cpp @@ -51,6 +51,19 @@ QT_BEGIN_NAMESPACE const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; +QPixmapData *QPixmapData::create(int w, int h, PixelType type) +{ + QPixmapData *data; + QGraphicsSystem* gs = QApplicationPrivate::graphicsSystem(); + if (gs) + data = gs->createPixmapData(static_cast<QPixmapData::PixelType>(type)); + else + data = QGraphicsSystem::createDefaultPixmapData(static_cast<QPixmapData::PixelType>(type)); + data->resize(w, h); + return data; +} + + QPixmapData::QPixmapData(PixelType pixelType, int objectId) : w(0), h(0), diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 2f4f201..d1bb92a 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -122,6 +122,8 @@ public: virtual void fromNativeType(void* pixmap, NativeType type); #endif + static QPixmapData *create(int w, int h, PixelType type); + protected: void setSerialNumber(int serNo); int w; @@ -131,12 +133,11 @@ protected: private: friend class QPixmap; - friend class QGLContextPrivate; friend class QX11PixmapData; friend class QS60PixmapData; + friend class QImagePixmapCleanupHooks; // Needs to set is_cached friend class QGLTextureCache; //Needs to check the reference count friend class QExplicitlySharedDataPointer<QPixmapData>; - friend bool qt_createEGLSurfaceForPixmap(QPixmapData*, bool); // Needs to set is_cached QAtomicInt ref; int detach_no; diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 9fcf776..e50cc8b 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -504,10 +504,10 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate { public: - QPixmapBlurFilterPrivate() : radius(5), hint(Qt::PerformanceHint) {} + QPixmapBlurFilterPrivate() : radius(5), hint(QGraphicsBlurEffect::PerformanceHint) {} - int radius; - Qt::RenderHint hint; + qreal radius; + QGraphicsBlurEffect::BlurHint hint; }; @@ -535,7 +535,7 @@ QPixmapBlurFilter::~QPixmapBlurFilter() \internal */ -void QPixmapBlurFilter::setRadius(int radius) +void QPixmapBlurFilter::setRadius(qreal radius) { Q_D(QPixmapBlurFilter); d->radius = radius; @@ -546,7 +546,7 @@ void QPixmapBlurFilter::setRadius(int radius) \internal */ -int QPixmapBlurFilter::radius() const +qreal QPixmapBlurFilter::radius() const { Q_D(const QPixmapBlurFilter); return d->radius; @@ -556,12 +556,18 @@ int QPixmapBlurFilter::radius() const Setting the blur hint to PerformanceHint causes the implementation to trade off visual quality to blur the image faster. Setting the blur hint to QualityHint causes the implementation to improve - visual quality at the expense of speed. The implementation is free - to ignore this value if it only has a single blur algorithm. + visual quality at the expense of speed. + + AnimationHint causes the implementation to optimize for animating + the blur radius, possibly by caching blurred versions of the source + pixmap. + + The implementation is free to ignore this value if it only has a single + blur algorithm. \internal */ -void QPixmapBlurFilter::setBlurHint(Qt::RenderHint hint) +void QPixmapBlurFilter::setBlurHint(QGraphicsBlurEffect::BlurHint hint) { Q_D(QPixmapBlurFilter); d->hint = hint; @@ -572,7 +578,7 @@ void QPixmapBlurFilter::setBlurHint(Qt::RenderHint hint) \internal */ -Qt::RenderHint QPixmapBlurFilter::blurHint() const +QGraphicsBlurEffect::BlurHint QPixmapBlurFilter::blurHint() const { Q_D(const QPixmapBlurFilter); return d->hint; @@ -584,7 +590,7 @@ Qt::RenderHint QPixmapBlurFilter::blurHint() const QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const { Q_D(const QPixmapBlurFilter); - const qreal delta = d->radius * 2; + const qreal delta = d->radius + 1; return rect.adjusted(-delta, -delta, delta, delta); } @@ -668,7 +674,7 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap if (!painter->isActive()) return; - if (d->radius == 0) { + if (d->radius <= 0) { painter->drawPixmap(srcRect.translated(p), src, srcRect); return; } @@ -688,12 +694,12 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap if (srcRect.isNull()) { srcImage = src.toImage(); - destImage = blurred(srcImage, srcImage.rect(), d->radius); + destImage = blurred(srcImage, srcImage.rect(), qRound(d->radius)); } else { QRect rect = srcRect.toAlignedRect().intersected(src.rect()); srcImage = src.copy(rect).toImage(); - destImage = blurred(srcImage, srcImage.rect(), d->radius); + destImage = blurred(srcImage, srcImage.rect(), qRound(d->radius)); } painter->drawImage(p, destImage); @@ -902,7 +908,7 @@ public: QPointF offset; QColor color; - int radius; + qreal radius; }; /*! @@ -966,7 +972,7 @@ QPixmapDropShadowFilter::~QPixmapDropShadowFilter() \internal */ -int QPixmapDropShadowFilter::blurRadius() const +qreal QPixmapDropShadowFilter::blurRadius() const { Q_D(const QPixmapDropShadowFilter); return d->radius; @@ -981,7 +987,7 @@ int QPixmapDropShadowFilter::blurRadius() const \internal */ -void QPixmapDropShadowFilter::setBlurRadius(int radius) +void QPixmapDropShadowFilter::setBlurRadius(qreal radius) { Q_D(QPixmapDropShadowFilter); d->radius = radius; @@ -1057,14 +1063,9 @@ void QPixmapDropShadowFilter::setOffset(const QPointF &offset) QRectF QPixmapDropShadowFilter::boundingRectFor(const QRectF &rect) const { Q_D(const QPixmapDropShadowFilter); - - const qreal delta = qreal(d->radius * 2); - qreal x1 = qMin(rect.left(), rect.left() + d->offset.x() - delta); - qreal y1 = qMin(rect.top(), rect.top() + d->offset.y() - delta); - qreal x2 = qMax(rect.right(), rect.right() + d->offset.x() + delta); - qreal y2 = qMax(rect.bottom(), rect.bottom() + d->offset.y() + delta); - - return QRectF(x1, y1, x2 - x1, y2 - y1); + qreal delta = d->radius + 1; + return rect.adjusted(-2, -2, 2, 2).united( + rect.translated(d->offset).adjusted(-delta, -delta, delta, delta)); } /*! @@ -1090,7 +1091,7 @@ void QPixmapDropShadowFilter::draw(QPainter *p, QImage tmp = src.isNull() ? px.toImage() : px.copy(src.toAlignedRect()).toImage(); // blur the alpha channel - tmp = blurred(tmp, tmp.rect(), d->radius, true); + tmp = blurred(tmp, tmp.rect(), qRound(d->radius), true); // blacken the image... QPainter tmpPainter(&tmp); diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 8a2207a..6a96676 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -55,6 +55,7 @@ #include <QtCore/qnamespace.h> #include <QtGui/qpixmap.h> +#include <QtGui/qgraphicseffect.h> QT_BEGIN_HEADER @@ -129,11 +130,11 @@ public: QPixmapBlurFilter(QObject *parent = 0); ~QPixmapBlurFilter(); - void setRadius(int radius); - void setBlurHint(Qt::RenderHint hint); + void setRadius(qreal radius); + void setBlurHint(QGraphicsBlurEffect::BlurHint hint); - int radius() const; - Qt::RenderHint blurHint() const; + qreal radius() const; + QGraphicsBlurEffect::BlurHint blurHint() const; QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; @@ -175,8 +176,8 @@ public: QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src = QRectF()) const; - int blurRadius() const; - void setBlurRadius(int radius); + qreal blurRadius() const; + void setBlurRadius(qreal radius); QColor color() const; void setColor(const QColor &color); diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index c4d17ff..3f21bc3 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -561,8 +561,28 @@ void QCoeFepInputContext::GetCursorSelectionForFep(TCursorSelection& aCursorSele int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt() + m_preeditString.size(); int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt() + m_preeditString.size(); - aCursorSelection.iAnchorPos = anchor; - aCursorSelection.iCursorPos = cursor; + QString text = w->inputMethodQuery(Qt::ImSurroundingText).value<QString>(); + int combinedSize = text.size() + m_preeditString.size(); + if (combinedSize < anchor || combinedSize < cursor) { + // ### TODO! FIXME! QTBUG-5050 + // This is a hack to prevent crashing in 4.6 with QLineEdits that use input masks. + // The root problem is that cursor position is relative to displayed text instead of the + // actual text we get. + // + // To properly fix this we would need to know the displayText of QLineEdits instead + // of just the text, which on itself should be a trivial change. The difficulties start + // when we need to commit the changes back to the QLineEdit, which would have to be somehow + // able to handle displayText, too. + // + // Until properly fixed, the cursor and anchor positions will not reflect correct positions + // for masked QLineEdits, unless all the masked positions are filled in order so that + // cursor position relative to the displayed text matches position relative to actual text. + aCursorSelection.iAnchorPos = combinedSize; + aCursorSelection.iCursorPos = combinedSize; + } else { + aCursorSelection.iAnchorPos = anchor; + aCursorSelection.iCursorPos = cursor; + } } void QCoeFepInputContext::GetEditorContentForFep(TDes& aEditorContent, TInt aDocumentPosition, diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp index e9ab870..ef2f5c0 100644 --- a/src/gui/inputmethod/qwininputcontext_win.cpp +++ b/src/gui/inputmethod/qwininputcontext_win.cpp @@ -327,28 +327,13 @@ static int getCursorPosition(HIMC himc) static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLength = 0) { - static wchar_t *buffer = 0; - static int buflen = 0; - - int len = getCompositionString(himc, dwindex, 0, 0) + 1; - if (!buffer || len > buflen) { - delete [] buffer; - buflen = qMin(len, 256); - buffer = new wchar_t[buflen]; - } - - len = getCompositionString(himc, dwindex, buffer, buflen * sizeof(wchar_t)); + const int bufferSize = 256; + wchar_t buffer[bufferSize]; + int len = getCompositionString(himc, dwindex, buffer, bufferSize * sizeof(wchar_t)); if (selStart) { - static wchar_t *attrbuffer = 0; - static int attrbuflen = 0; - int attrlen = getCompositionString(himc, dwindex, 0, 0) + 1; - if (!attrbuffer || attrlen> attrbuflen) { - delete [] attrbuffer; - attrbuflen = qMin(attrlen, 256); - attrbuffer = new wchar_t[attrbuflen]; - } - attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, attrbuflen * sizeof(wchar_t)); + char attrbuffer[bufferSize]; + int attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, bufferSize); *selStart = attrlen+1; *selLength = -1; for (int i = 0; i < attrlen; i++) { diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index d91cedd..23bef12 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -605,6 +605,8 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) this, SLOT(_q_modelDestroyed())); disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex,QModelIndex))); + disconnect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), + this, SLOT(_q_headerDataChanged())); disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted(QModelIndex,int,int))); disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), @@ -637,6 +639,8 @@ void QAbstractItemView::setModel(QAbstractItemModel *model) this, SLOT(_q_modelDestroyed())); connect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(dataChanged(QModelIndex,QModelIndex))); + connect(d->model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), + this, SLOT(_q_headerDataChanged())); connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(rowsInserted(QModelIndex,int,int))); connect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), @@ -3637,7 +3641,7 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::extendedSelectionC const bool controlKeyPressed = modifiers & Qt::ControlModifier; if (((index == pressedIndex && selectionModel->isSelected(index)) || !index.isValid()) && state != QAbstractItemView::DragSelectingState - && !shiftKeyPressed && !controlKeyPressed && !rightButtonPressed) + && !shiftKeyPressed && !controlKeyPressed && (!rightButtonPressed || !index.isValid())) return QItemSelectionModel::ClearAndSelect|selectionBehaviorFlags(); return QItemSelectionModel::NoUpdate; } diff --git a/src/gui/itemviews/qabstractitemview.h b/src/gui/itemviews/qabstractitemview.h index b4f0957..7a0509b 100644 --- a/src/gui/itemviews/qabstractitemview.h +++ b/src/gui/itemviews/qabstractitemview.h @@ -358,9 +358,11 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex&, int, int)) Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed()) Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged()) + Q_PRIVATE_SLOT(d_func(), void _q_headerDataChanged()) friend class QTreeViewPrivate; // needed to compile with MSVC friend class QAccessibleItemRow; + friend class QListModeViewBase; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractItemView::EditTriggers) diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index fcf381a..c691f61 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -117,6 +117,7 @@ public: virtual void _q_columnsInserted(const QModelIndex &parent, int start, int end); virtual void _q_modelDestroyed(); virtual void _q_layoutChanged(); + void _q_headerDataChanged() { doDelayedItemsLayout(); } void fetchMore(); @@ -164,7 +165,8 @@ public: } #ifndef QT_NO_DRAGANDDROP - QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + inline bool canDecode(QDropEvent *e) const { QStringList modelTypes = model->mimeTypes(); const QMimeData *mime = e->mimeData(); diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp index 2973741..942cfd7 100644 --- a/src/gui/itemviews/qdirmodel.cpp +++ b/src/gui/itemviews/qdirmodel.cpp @@ -1351,7 +1351,7 @@ QString QDirModelPrivate::size(const QModelIndex &index) const return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', 1)); if (bytes >= kb) return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb)); - return QFileSystemModel::tr("%1 bytes").arg(QLocale().toString(bytes)); + return QFileSystemModel::tr("%1 byte(s)").arg(QLocale().toString(bytes)); } QString QDirModelPrivate::type(const QModelIndex &index) const diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp index e3d17ad..6316797 100644 --- a/src/gui/itemviews/qfileiconprovider.cpp +++ b/src/gui/itemviews/qfileiconprovider.cpp @@ -47,24 +47,24 @@ #include <qdir.h> #include <qpixmapcache.h> #if defined(Q_WS_WIN) -#define _WIN32_IE 0x0500 -#include <qt_windows.h> -#include <commctrl.h> -#include <objbase.h> +# define _WIN32_IE 0x0500 +# include <qt_windows.h> +# include <commctrl.h> +# include <objbase.h> #elif defined(Q_WS_MAC) -#include <private/qt_cocoa_helpers_mac_p.h> -#endif - -#if defined(Q_WS_X11) && !defined(Q_NO_STYLE_GTK) -#include <private/qt_x11_p.h> -#include <private/gtksymbols_p.h> +# include <private/qt_cocoa_helpers_mac_p.h> #endif #include <private/qfunctions_p.h> #include <private/qguiplatformplugin_p.h> +#if defined(Q_WS_X11) && !defined(Q_NO_STYLE_GTK) +# include <private/qgtkstyle_p.h> +# include <private/qt_x11_p.h> +#endif + #ifndef SHGFI_ADDOVERLAYS -#define SHGFI_ADDOVERLAYS 0x000000020 +# define SHGFI_ADDOVERLAYS 0x000000020 #endif QT_BEGIN_NAMESPACE @@ -392,7 +392,7 @@ QIcon QFileIconProvider::icon(const QFileInfo &info) const #if defined(Q_WS_X11) && !defined(QT_NO_STYLE_GTK) if (X11->desktopEnvironment == DE_GNOME) { - QIcon gtkIcon = QGtk::getFilesystemIcon(info); + QIcon gtkIcon = QGtkStylePrivate::getFilesystemIcon(info); if (!gtkIcon.isNull()) return gtkIcon; } diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp index fc9820f..6f2cff9 100644 --- a/src/gui/itemviews/qheaderview.cpp +++ b/src/gui/itemviews/qheaderview.cpp @@ -1419,7 +1419,7 @@ int QHeaderView::minimumSectionSize() const int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this); if (d->orientation == Qt::Horizontal) return qMax(strut.width(), (fontMetrics().maxWidth() + margin)); - return qMax(strut.height(), (fontMetrics().lineSpacing() + margin)); + return qMax(strut.height(), (fontMetrics().height() + margin)); } return d->minimumSectionSize; } @@ -2516,6 +2516,8 @@ QSize QHeaderView::sectionSizeFromContents(int logicalIndex) const Q_D(const QHeaderView); Q_ASSERT(logicalIndex >= 0); + ensurePolished(); + // use SizeHintRole QVariant variant = d->model->headerData(logicalIndex, d->orientation, Qt::SizeHintRole); if (variant.isValid()) diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 871a4b1..3b3036d 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -255,7 +255,7 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const \row \o \l Qt::BackgroundRole \o QBrush \row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead) \row \o \l Qt::CheckStateRole \o Qt::CheckState - \row \o \l Qt::DecorationRole \o QIcon and QColor + \row \o \l Qt::DecorationRole \o QIcon, QPixmap and QColor \row \o \l Qt::DisplayRole \o QString and types with a string representation \row \o \l Qt::EditRole \o See QItemEditorFactory for details \row \o \l Qt::FontRole \o QFont diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index dfebe03..c6e02a6 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -599,7 +599,7 @@ void QItemSelectionModelPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &pare while (itParent.isValid() && itParent.parent() != parent) itParent = itParent.parent(); - if (parent.isValid() && start <= itParent.row() && itParent.row() <= end) { + if (itParent.isValid() && start <= itParent.row() && itParent.row() <= end) { deselected.append(*it); it = ranges.erase(it); } else { @@ -1587,7 +1587,8 @@ void QItemSelectionModel::emitSelectionChanged(const QItemSelection &newSelectio } } - emit selectionChanged(selected, deselected); + if (!selected.isEmpty() || !deselected.isEmpty()) + emit selectionChanged(selected, deselected); } #ifndef QT_NO_DEBUG_STREAM diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 1d9b6e0..d680af8 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -853,8 +853,13 @@ void QListView::resizeEvent(QResizeEvent *e) */ void QListView::dragMoveEvent(QDragMoveEvent *e) { - if (!d_func()->commonListView->filterDragMoveEvent(e)) - QAbstractItemView::dragMoveEvent(e); + Q_D(QListView); + if (!d->commonListView->filterDragMoveEvent(e)) { + if (viewMode() == QListView::ListMode && flow() == QListView::LeftToRight) + static_cast<QListModeViewBase *>(d->commonListView)->dragMoveEvent(e); + else + QAbstractItemView::dragMoveEvent(e); + } } @@ -1804,6 +1809,16 @@ QItemSelection QListViewPrivate::selection(const QRect &rect) const return selection; } +#ifndef QT_NO_DRAGANDDROP +QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const +{ + if (viewMode == QListView::ListMode && flow == QListView::LeftToRight) + return static_cast<QListModeViewBase *>(commonListView)->position(pos, rect, idx); + else + return QAbstractItemViewPrivate::position(pos, rect, idx); +} +#endif + /* * Common ListView Implementation */ @@ -1893,6 +1908,96 @@ void QListModeViewBase::paintDragDrop(QPainter *painter) // in IconMode, it makes no sense to show it dd->paintDropIndicator(painter); } + +QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const +{ + QAbstractItemView::DropIndicatorPosition r = QAbstractItemView::OnViewport; + if (!dd->overwrite) { + const int margin = 2; + if (pos.x() - rect.left() < margin) { + r = QAbstractItemView::AboveItem; // Visually, on the left + } else if (rect.right() - pos.x() < margin) { + r = QAbstractItemView::BelowItem; // Visually, on the right + } else if (rect.contains(pos, true)) { + r = QAbstractItemView::OnItem; + } + } else { + QRect touchingRect = rect; + touchingRect.adjust(-1, -1, 1, 1); + if (touchingRect.contains(pos, false)) { + r = QAbstractItemView::OnItem; + } + } + + if (r == QAbstractItemView::OnItem && (!(dd->model->flags(index) & Qt::ItemIsDropEnabled))) + r = pos.x() < rect.center().x() ? QAbstractItemView::AboveItem : QAbstractItemView::BelowItem; + + return r; +} + +void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) +{ + if (qq->dragDropMode() == QAbstractItemView::InternalMove + && (event->source() != qq || !(event->possibleActions() & Qt::MoveAction))) + return; + + // ignore by default + event->ignore(); + + QModelIndex index = qq->indexAt(event->pos()); + dd->hover = index; + if (!dd->droppingOnItself(event, index) + && dd->canDecode(event)) { + + if (index.isValid() && dd->showDropIndicator) { + QRect rect = qq->visualRect(index); + dd->dropIndicatorPosition = position(event->pos(), rect, index); + switch (dd->dropIndicatorPosition) { + case QAbstractItemView::AboveItem: + if (dd->isIndexDropEnabled(index.parent())) { + dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height()); + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::BelowItem: + if (dd->isIndexDropEnabled(index.parent())) { + dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height()); + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::OnItem: + if (dd->isIndexDropEnabled(index)) { + dd->dropIndicatorRect = rect; + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::OnViewport: + dd->dropIndicatorRect = QRect(); + if (dd->isIndexDropEnabled(qq->rootIndex())) { + event->accept(); // allow dropping in empty areas + } + break; + } + } else { + dd->dropIndicatorRect = QRect(); + dd->dropIndicatorPosition = QAbstractItemView::OnViewport; + if (dd->isIndexDropEnabled(qq->rootIndex())) { + event->accept(); // allow dropping in empty areas + } + } + dd->viewport->update(); + } // can decode + + if (dd->shouldAutoScroll(event->pos())) + qq->startAutoScroll(); +} + #endif //QT_NO_DRAGANDDROP void QListModeViewBase::updateVerticalScrollBar(const QSize &step) @@ -1900,7 +2005,7 @@ void QListModeViewBase::updateVerticalScrollBar(const QSize &step) if (verticalScrollMode() == QAbstractItemView::ScrollPerItem && ((flow() == QListView::TopToBottom && !isWrapping()) || (flow() == QListView::LeftToRight && isWrapping()))) { - const int steps = (flow() == QListView::TopToBottom ? flowPositions : segmentPositions).count() - 1; + const int steps = (flow() == QListView::TopToBottom ? scrollValueMap : segmentPositions).count() - 1; if (steps > 0) { const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping()); verticalScrollBar()->setSingleStep(1); @@ -1921,7 +2026,7 @@ void QListModeViewBase::updateHorizontalScrollBar(const QSize &step) if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem && ((flow() == QListView::TopToBottom && isWrapping()) || (flow() == QListView::LeftToRight && !isWrapping()))) { - int steps = (flow() == QListView::TopToBottom ? segmentPositions : flowPositions).count() - 1; + int steps = (flow() == QListView::TopToBottom ? segmentPositions : scrollValueMap).count() - 1; if (steps > 0) { const int pageSteps = perItemScrollingPageSteps(viewport()->width(), contentsSize.width(), isWrapping()); horizontalScrollBar()->setSingleStep(1); @@ -1939,7 +2044,11 @@ int QListModeViewBase::verticalScrollToValue(int index, QListView::ScrollHint hi bool above, bool below, const QRect &area, const QRect &rect) const { if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { - int value = qBound(0, verticalScrollBar()->value(), flowPositions.count() - 1); + int value; + if (scrollValueMap.isEmpty()) + value = 0; + else + value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()), flowPositions.count() - 1); if (above) hint = QListView::PositionAtTop; else if (below) @@ -1966,8 +2075,8 @@ int QListModeViewBase::horizontalOffset() const return (isRightToLeft() ? maximum - position : position); } } else if (flow() == QListView::LeftToRight && !flowPositions.isEmpty()) { - int position = flowPositions.at(horizontalScrollBar()->value()); - int maximum = flowPositions.at(horizontalScrollBar()->maximum()); + int position = flowPositions.at(scrollValueMap.at(horizontalScrollBar()->value())); + int maximum = flowPositions.at(scrollValueMap.at(horizontalScrollBar()->maximum())); return (isRightToLeft() ? maximum - position : position); } } @@ -1986,9 +2095,9 @@ int QListModeViewBase::verticalOffset() const } } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) { int value = verticalScrollBar()->value(); - if (value > flowPositions.count()) + if (value > scrollValueMap.count()) return 0; - return flowPositions.at(value) - spacing(); + return flowPositions.at(scrollValueMap.at(value)) - spacing(); } } return QCommonListViewBase::verticalOffset(); @@ -2000,7 +2109,11 @@ int QListModeViewBase::horizontalScrollToValue(int index, QListView::ScrollHint if (horizontalScrollMode() != QAbstractItemView::ScrollPerItem) return QCommonListViewBase::horizontalScrollToValue(index, hint, leftOf, rightOf, area, rect); - int value = qBound(0, horizontalScrollBar()->value(), flowPositions.count() - 1); + int value; + if (scrollValueMap.isEmpty()) + value = 0; + else + value = qBound(0, scrollValueMap.at(horizontalScrollBar()->value()), flowPositions.count() - 1); if (leftOf) hint = QListView::PositionAtTop; else if (rightOf) @@ -2043,14 +2156,14 @@ void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand) if (vertical && flow() == QListView::TopToBottom && dy != 0) { int currentValue = qBound(0, verticalValue, max); int previousValue = qBound(0, currentValue + dy, max); - int currentCoordinate = flowPositions.at(currentValue); - int previousCoordinate = flowPositions.at(previousValue); + int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue)); + int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue)); dy = previousCoordinate - currentCoordinate; } else if (horizontal && flow() == QListView::LeftToRight && dx != 0) { int currentValue = qBound(0, horizontalValue, max); int previousValue = qBound(0, currentValue + dx, max); - int currentCoordinate = flowPositions.at(currentValue); - int previousCoordinate = flowPositions.at(previousValue); + int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue)); + int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue)); dx = previousCoordinate - currentCoordinate; } } @@ -2113,6 +2226,7 @@ QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info) segmentPositions.clear(); segmentStartRows.clear(); segmentExtents.clear(); + scrollValueMap.clear(); x = info.bounds.left() + info.spacing; y = info.bounds.top() + info.spacing; segmentPositions.append(info.flow == QListView::LeftToRight ? y : x); @@ -2204,6 +2318,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) deltaSegPosition = 0; } // save the flow position of this item + scrollValueMap.append(flowPositions.count()); flowPositions.append(flowPosition); // prepare for the next item deltaSegPosition = qMax(deltaSegHint, deltaSegPosition); @@ -2229,6 +2344,7 @@ void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info) // if it is the last batch, save the end of the segments if (info.last == info.max) { segmentExtents.append(flowPosition); + scrollValueMap.append(flowPositions.count()); flowPositions.append(flowPosition); segmentPositions.append(info.wrap ? segPosition + deltaSegPosition : INT_MAX); } @@ -2287,6 +2403,12 @@ QVector<QModelIndex> QListModeViewBase::intersectingSet(const QRect &area) const return ret; } +void QListModeViewBase::dataChanged(const QModelIndex &, const QModelIndex &) +{ + dd->doDelayedItemsLayout(); +} + + QRect QListModeViewBase::mapToViewport(const QRect &rect) const { if (isWrapping()) @@ -2306,7 +2428,14 @@ QRect QListModeViewBase::mapToViewport(const QRect &rect) const int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const { - const QVector<int> positions = (wrap ? segmentPositions : flowPositions); + QVector<int> positions; + if (wrap) + positions = segmentPositions; + else if (!flowPositions.isEmpty()) { + positions.reserve(scrollValueMap.size()); + foreach (int itemShown, scrollValueMap) + positions.append(flowPositions.at(itemShown)); + } if (positions.isEmpty() || bounds <= length) return positions.count(); if (uniformItemSizes()) { diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index b6785da..31459b0 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -130,6 +130,7 @@ public: virtual void clear() = 0; virtual void setRowCount(int) = 0; virtual QVector<QModelIndex> intersectingSet(const QRect &area) const = 0; + virtual void dataChanged(const QModelIndex &, const QModelIndex &) = 0; virtual int horizontalScrollToValue(int index, QListView::ScrollHint hint, bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const; @@ -141,7 +142,6 @@ public: virtual int verticalOffset() const { return verticalScrollBar()->value(); } virtual void updateHorizontalScrollBar(const QSize &step); virtual void updateVerticalScrollBar(const QSize &step); - virtual void dataChanged(const QModelIndex &, const QModelIndex &) { } virtual void appendHiddenRow(int row); virtual void removeHiddenRow(int row); virtual void setPositionForIndex(const QPoint &, const QModelIndex &) { } @@ -205,6 +205,7 @@ public: QVector<int> segmentPositions; QVector<int> segmentStartRows; QVector<int> segmentExtents; + QVector<int> scrollValueMap; // used when laying out in batches int batchSavedPosition; @@ -216,6 +217,7 @@ public: void clear(); void setRowCount(int rowCount) { flowPositions.resize(rowCount); } QVector<QModelIndex> intersectingSet(const QRect &area) const; + void dataChanged(const QModelIndex &, const QModelIndex &); int horizontalScrollToValue(int index, QListView::ScrollHint hint, bool leftOf, bool rightOf,const QRect &area, const QRect &rect) const; @@ -230,6 +232,11 @@ public: #ifndef QT_NO_DRAGANDDROP void paintDragDrop(QPainter *painter); + + // The next two methods are to be used on LefToRight flow only. + // WARNING: Plenty of duplicated code from QAbstractItemView{,Private}. + QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; + void dragMoveEvent(QDragMoveEvent *e); #endif private: @@ -355,6 +362,10 @@ public: QItemSelection selection(const QRect &rect) const; void selectAll(QItemSelectionModel::SelectionFlags command); +#ifndef QT_NO_DRAGANDDROP + virtual QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const; +#endif + inline void setGridSize(const QSize &size) { grid = size; } inline QSize gridSize() const { return grid; } inline void setWrapping(bool b) { wrap = b; } diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp index a978d0f..5dd1d76 100644 --- a/src/gui/itemviews/qlistwidget.cpp +++ b/src/gui/itemviews/qlistwidget.cpp @@ -169,6 +169,20 @@ QListWidgetItem *QListModel::take(int row) return item; } +void QListModel::move(int srcRow, int dstRow) +{ + if (srcRow == dstRow + || srcRow < 0 || srcRow >= items.count() + || dstRow < 0 || dstRow >= items.count()) + return; + + beginMoveRows(QModelIndex(), srcRow, srcRow, QModelIndex(), dstRow); + if (srcRow < dstRow) + --dstRow; + items.move(srcRow, dstRow); + endMoveRows(); +} + int QListModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : items.count(); @@ -1804,22 +1818,15 @@ void QListWidget::dropEvent(QDropEvent *event) { if (persIndexes.contains(topIndex)) return; + qSort(persIndexes); // The dropped items will remain in the same visual order. QPersistentModelIndex dropRow = model()->index(row, col, topIndex); - QList<QListWidgetItem *> taken; - for (int i = 0; i < persIndexes.count(); ++i) - taken.append(takeItem(persIndexes.at(i).row())); - - // insert them back in at their new positions + int r = row == -1 ? count() : (dropRow.row() >= 0 ? dropRow.row() : row); for (int i = 0; i < persIndexes.count(); ++i) { - // Either at a specific point or appended - if (row == -1) { - insertItem(count(), taken.takeFirst()); - } else { - int r = dropRow.row() >= 0 ? dropRow.row() : row; - insertItem(qMin(r, count()), taken.takeFirst()); - } + const QPersistentModelIndex &pIndex = persIndexes.at(i); + d->listModel()->move(pIndex.row(), r); + r = pIndex.row() + 1; // Dropped items are inserted contiguously and in the right order. } event->accept(); diff --git a/src/gui/itemviews/qlistwidget_p.h b/src/gui/itemviews/qlistwidget_p.h index 69cfa26..b5f28e3 100644 --- a/src/gui/itemviews/qlistwidget_p.h +++ b/src/gui/itemviews/qlistwidget_p.h @@ -77,7 +77,7 @@ public: { return *i2 < *i1; } }; -class QListModel : public QAbstractListModel +class Q_AUTOTEST_EXPORT QListModel : public QAbstractListModel { Q_OBJECT public: @@ -90,6 +90,7 @@ public: void insert(int row, const QStringList &items); void remove(QListWidgetItem *item); QListWidgetItem *take(int row); + void move(int srcRow, int dstRow); int rowCount(const QModelIndex &parent = QModelIndex()) const; diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index 1c36787..1ca0391 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -148,7 +148,7 @@ public: \row \o \l Qt::BackgroundRole \o QBrush \row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead) \row \o \l Qt::CheckStateRole \o Qt::CheckState - \row \o \l Qt::DecorationRole \o QIcon and QColor + \row \o \l Qt::DecorationRole \o QIcon, QPixmap, QImage and QColor \row \o \l Qt::DisplayRole \o QString and types with a string representation \row \o \l Qt::EditRole \o See QItemEditorFactory for details \row \o \l Qt::FontRole \o QFont diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 2a937f1..02e5fff 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -117,7 +117,7 @@ void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height) Index::iterator it_y = index.lowerBound(-span->bottom()); Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list while (-it_y.key() <= span->top() + old_height -1) { - if(-it_y.key() != span->bottom()) { + if (-it_y.key() > span->bottom()) { (*it_y).remove(-span->left()); if (it_y->isEmpty()) { it_y = index.erase(it_y) - 1; @@ -544,6 +544,47 @@ void QSpanCollection::updateRemovedColumns(int start, int end) qDeleteAll(toBeDeleted); } +#ifdef QT_BUILD_INTERNAL +/*! + \internal + Checks whether the span index structure is self-consistent, and consistent with the spans list. +*/ +bool QSpanCollection::checkConsistency() const +{ + for (Index::const_iterator it_y = index.begin(); it_y != index.end(); ++it_y) { + int y = -it_y.key(); + const SubIndex &subIndex = it_y.value(); + for (SubIndex::const_iterator it = subIndex.begin(); it != subIndex.end(); ++it) { + int x = -it.key(); + Span *span = it.value(); + if (!spans.contains(span) || span->left() != x + || y < span->top() || y > span->bottom()) + return false; + } + } + + foreach (const Span *span, spans) { + if (span->width() < 1 || span->height() < 1 + || (span->width() == 1 && span->height() == 1)) + return false; + for (int y = span->top(); y <= span->bottom(); ++y) { + Index::const_iterator it_y = index.find(-y); + if (it_y == index.end()) { + if (y == span->top()) + return false; + else + continue; + } + const SubIndex &subIndex = it_y.value(); + SubIndex::const_iterator it = subIndex.find(-span->left()); + if (it == subIndex.end() || it.value() != span) + return false; + } + } + return true; +} +#endif + class QTableCornerButton : public QAbstractButton { Q_OBJECT @@ -2065,6 +2106,8 @@ int QTableView::sizeHintForRow(int row) const if (!model()) return -1; + ensurePolished(); + int left = qMax(0, columnAt(0)); int right = columnAt(d->viewport->width()); if (right == -1) // the table don't have enough columns to fill the viewport @@ -2122,6 +2165,8 @@ int QTableView::sizeHintForColumn(int column) const if (!model()) return -1; + ensurePolished(); + int top = qMax(0, rowAt(0)); int bottom = rowAt(d->viewport->height()); if (!isVisible() || bottom == -1) // the table don't have enough rows to fill the viewport diff --git a/src/gui/itemviews/qtableview_p.h b/src/gui/itemviews/qtableview_p.h index 9fa14c2..6b19ded 100644 --- a/src/gui/itemviews/qtableview_p.h +++ b/src/gui/itemviews/qtableview_p.h @@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE * The key of the first map is the row where the subspan starts, the value of the first map is * a list (map) of all subspans that starts at the same row. It is indexed with its row */ -class QSpanCollection +class Q_AUTOTEST_EXPORT QSpanCollection { public: struct Span @@ -112,6 +112,10 @@ public: void updateRemovedRows(int start, int end); void updateRemovedColumns(int start, int end); +#ifdef QT_BUILD_INTERNAL + bool checkConsistency() const; +#endif + typedef QLinkedList<Span *> SpanList; SpanList spans; //lists of all spans private: diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 210534e..3856293 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -1226,8 +1226,12 @@ bool QTreeView::viewportEvent(QEvent *event) if (oldIndex != newIndex) { QRect oldRect = visualRect(oldIndex); QRect newRect = visualRect(newIndex); - viewport()->update(oldRect.left() - d->indent, oldRect.top(), d->indent, oldRect.height()); - viewport()->update(newRect.left() - d->indent, newRect.top(), d->indent, newRect.height()); + oldRect.setLeft(oldRect.left() - d->indent); + newRect.setLeft(newRect.left() - d->indent); + //we need to paint the whole items (including the decoration) so that when the user + //moves the mouse over those elements they are updated + viewport()->update(oldRect); + viewport()->update(newRect); } } if (selectionBehavior() == QAbstractItemView::SelectRows) { @@ -1422,8 +1426,9 @@ void QTreeView::drawTree(QPainter *painter, const QRegion ®ion) const for (; i < viewItems.count() && y <= area.bottom(); ++i) { const int itemHeight = d->itemHeight(i); option.rect.setRect(0, y, viewportWidth, itemHeight); - option.state = state | (viewItems.at(i).expanded - ? QStyle::State_Open : QStyle::State_None); + option.state = state | (viewItems.at(i).expanded ? QStyle::State_Open : QStyle::State_None) + | (viewItems.at(i).hasChildren ? QStyle::State_Children : QStyle::State_None) + | (viewItems.at(i).hasMoreSiblings ? QStyle::State_Sibling : QStyle::State_None); d->current = i; d->spanning = viewItems.at(i).spanning; if (!multipleRects || !drawn.contains(i)) { @@ -1748,14 +1753,8 @@ void QTreeView::drawBranches(QPainter *painter, const QRect &rect, opt.rect = primitive; const bool expanded = viewItem.expanded; - const bool children = (((expanded && viewItem.total > 0)) // already laid out and has children - || d->hasVisibleChildren(index)); // not laid out yet, so we don't know - bool moreSiblings = false; - if (d->hiddenIndexes.isEmpty()) - moreSiblings = (d->model->rowCount(parent) - 1 > index.row()); - else - moreSiblings = ((d->viewItems.size() > item +1) - && (d->viewItems.at(item + 1).index.parent() == parent)); + const bool children = viewItem.hasChildren; + bool moreSiblings = viewItem.hasMoreSiblings; opt.state = QStyle::State_Item | extraFlags | (moreSiblings ? QStyle::State_Sibling : QStyle::State_None) @@ -1845,9 +1844,7 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event) return; // user clicked outside the items const QPersistentModelIndex firstColumnIndex = d->viewItems.at(i).index; - - int column = d->header->logicalIndexAt(event->x()); - QPersistentModelIndex persistent = firstColumnIndex.sibling(firstColumnIndex.row(), column); + const QPersistentModelIndex persistent = indexAt(event->pos()); if (d->pressedIndex != persistent) { mousePressEvent(event); @@ -2437,7 +2434,9 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) return; } - if (parent != d->root && !d->isIndexExpanded(parent) && d->model->rowCount(parent) > (end - start) + 1) { + const int parentRowCount = d->model->rowCount(parent); + const int delta = end - start + 1; + if (parent != d->root && !d->isIndexExpanded(parent) && parentRowCount > delta) { QAbstractItemView::rowsInserted(parent, start, end); return; } @@ -2452,11 +2451,29 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) ? d->viewItems.count() : d->viewItems.at(parentItem).total) - 1; - const int delta = end - start + 1; + if (parentRowCount == end + 1 && start > 0) { + //need to Update hasMoreSiblings + int previousRow = start - 1; + QModelIndex previousSibilingModelIndex = d->model->index(previousRow, 0, parent); + bool isHidden = d->isRowHidden(previousSibilingModelIndex); + while (isHidden && previousRow > 0) { + previousRow--; + previousSibilingModelIndex = d->model->index(previousRow, 0, parent); + isHidden = d->isRowHidden(previousSibilingModelIndex); + } + if (!isHidden) { + const int previousSibilling = d->viewIndex(previousSibilingModelIndex); + if(previousSibilling != -1) + d->viewItems[previousSibilling].hasMoreSiblings = true; + } + } + QVector<QTreeViewItem> insertedItems(delta); for (int i = 0; i < delta; ++i) { insertedItems[i].index = d->model->index(i + start, 0, parent); insertedItems[i].level = childLevel; + insertedItems[i].hasChildren = d->hasVisibleChildren(insertedItems[i].index); + insertedItems[i].hasMoreSiblings = !((i == delta - 1) && (parentRowCount == end +1)); } if (d->viewItems.isEmpty()) d->defaultItemHeight = indexRowSizeHint(insertedItems[0].index); @@ -2498,13 +2515,17 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end) d->viewItems.begin() + insertPos + 1); } + if (parentItem != -1) + d->viewItems[parentItem].hasChildren = true; d->updateChildCount(parentItem, delta); + updateGeometries(); viewport()->update(); } else if ((parentItem != -1) && d->viewItems.at(parentItem).expanded) { d->doDelayedItemsLayout(); } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) { - // the parent just went from 0 children to having some update to re-paint the decoration + // the parent just went from 0 children to more. update to re-paint the decoration + d->viewItems[parentItem].hasChildren = true; viewport()->update(); } QAbstractItemView::rowsInserted(parent, start, end); @@ -2908,6 +2929,8 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) layout(item); q->setState(oldState); + if (model->canFetchMore(index)) + model->fetchMore(index); if (emitSignal) { emit q->expanded(index); #ifndef QT_NO_ANIMATION @@ -2915,8 +2938,6 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) beginAnimatedOperation(); #endif //QT_NO_ANIMATION } - if (model->canFetchMore(index)) - model->fetchMore(index); } void QTreeViewPrivate::collapse(int item, bool emitSignal) @@ -3005,10 +3026,12 @@ void QTreeViewPrivate::beginAnimatedOperation() animatedOperation.setEndValue(animatedOperation.top() + h); } - animatedOperation.after = renderTreeToPixmapForAnimation(rect); + if (!rect.isEmpty()) { + animatedOperation.after = renderTreeToPixmapForAnimation(rect); - q->setState(QAbstractItemView::AnimatingState); - animatedOperation.start(); //let's start the animation + q->setState(QAbstractItemView::AnimatingState); + animatedOperation.start(); //let's start the animation + } } void QTreeViewPrivate::drawAnimatedOperation(QPainter *painter) const @@ -3125,7 +3148,7 @@ void QTreeViewPrivate::layout(int i) int hidden = 0; int last = 0; int children = 0; - + QTreeViewItem *item = 0; for (int j = first; j < first + count; ++j) { current = model->index(j - first, 0, parent); if (isRowHidden(current)) { @@ -3133,17 +3156,25 @@ void QTreeViewPrivate::layout(int i) last = j - hidden + children; } else { last = j - hidden + children; - viewItems[last].index = current; - viewItems[last].level = level; - viewItems[last].height = 0; - viewItems[last].spanning = q->isFirstColumnSpanned(current.row(), parent); - viewItems[last].expanded = false; - viewItems[last].total = 0; + if (item) + item->hasMoreSiblings = true; + item = &viewItems[last]; + item->index = current; + item->level = level; + item->height = 0; + item->spanning = q->isFirstColumnSpanned(current.row(), parent); + item->expanded = false; + item->total = 0; + item->hasMoreSiblings = false; if (isIndexExpanded(current)) { - viewItems[last].expanded = true; + item->expanded = true; layout(last); - children += viewItems[last].total; + item = &viewItems[last]; + children += item->total; + item->hasChildren = item->total > 0; last = j - hidden + children; + } else { + item->hasChildren = hasVisibleChildren(current); } } } @@ -3699,6 +3730,7 @@ void QTreeViewPrivate::rowsRemoved(const QModelIndex &parent, const int delta = end - start + 1; + int previousSibiling = -1; int removedCount = 0; for (int item = firstChildItem; item <= lastChildItem; ) { Q_ASSERT(viewItems.at(item).level == childLevel); @@ -3706,6 +3738,7 @@ void QTreeViewPrivate::rowsRemoved(const QModelIndex &parent, //Q_ASSERT(modelIndex.parent() == parent); const int count = viewItems.at(item).total + 1; if (modelIndex.row() < start) { + previousSibiling = item; // not affected by the removal item += count; } else if (modelIndex.row() <= end) { @@ -3723,7 +3756,13 @@ void QTreeViewPrivate::rowsRemoved(const QModelIndex &parent, } } + if (previousSibiling != -1 && after && model->rowCount(parent) == start) + viewItems[previousSibiling].hasMoreSiblings = false; + + updateChildCount(parentItem, -removedCount); + if (parentItem != -1 && viewItems.at(parentItem).total == 0) + viewItems[parentItem].hasChildren = false; //every children have been removed; if (after) { q->updateGeometries(); viewport->update(); diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index def8253..aad5837 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -62,11 +62,14 @@ QT_BEGIN_NAMESPACE struct QTreeViewItem { - QTreeViewItem() : expanded(false), spanning(false), total(0), level(0), height(0) {} + QTreeViewItem() : expanded(false), spanning(false), hasChildren(false), + hasMoreSiblings(false), total(0), level(0), height(0) {} QModelIndex index; // we remove items whenever the indexes are invalidated uint expanded : 1; uint spanning : 1; - uint total : 30; // total number of children visible + uint hasChildren : 1; // if the item has visible children (even if collapsed) + uint hasMoreSiblings : 1; + uint total : 28; // total number of children visible uint level : 16; // indentation int height : 16; // row height }; diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 53c2611..8859358 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -84,6 +84,7 @@ SOURCES += \ kernel/qgesturerecognizer.cpp \ kernel/qgesturemanager.cpp \ kernel/qsoftkeymanager.cpp \ + kernel/qdesktopwidget.cpp \ kernel/qguiplatformplugin.cpp win32 { diff --git a/src/gui/kernel/qactiongroup.cpp b/src/gui/kernel/qactiongroup.cpp index 40d18a2..8db76e4 100644 --- a/src/gui/kernel/qactiongroup.cpp +++ b/src/gui/kernel/qactiongroup.cpp @@ -72,10 +72,16 @@ void QActionGroupPrivate::_q_actionChanged() Q_Q(QActionGroup); QAction *action = qobject_cast<QAction*>(q->sender()); Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionChanged", "internal error"); - if(exclusive && action->isChecked() && action != current) { - if(current) - current->setChecked(false); - current = action; + if(exclusive) { + if (action->isChecked()) { + if (action != current) { + if(current) + current->setChecked(false); + current = action; + } + } else if (action == current) { + current = 0; + } } } diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 873f321..0f3236c 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -474,9 +474,6 @@ bool QApplicationPrivate::fade_tooltip = false; bool QApplicationPrivate::animate_toolbox = false; bool QApplicationPrivate::widgetCount = false; bool QApplicationPrivate::load_testability = false; -#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) -bool QApplicationPrivate::inSizeMove = false; -#endif #ifdef QT_KEYPAD_NAVIGATION # ifdef Q_OS_SYMBIAN Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; @@ -948,12 +945,8 @@ void QApplicationPrivate::initialize() graphics_system = QGraphicsSystemFactory::create(graphics_system_name); #endif #ifndef QT_NO_WHEELEVENT -#ifdef Q_OS_MAC - QApplicationPrivate::wheel_scroll_lines = 1; -#else QApplicationPrivate::wheel_scroll_lines = 3; #endif -#endif initializeMultitouch(); } @@ -2093,7 +2086,7 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) } QWidget *prev = focus_widget; focus_widget = focus; - +#ifndef QT_NO_IM if (prev && ((reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason && prev->testAttribute(Qt::WA_InputMethodEnabled)) // Do reset the input context, in case the new focus widget won't accept keyboard input @@ -2106,6 +2099,7 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) qic->setFocusWidget(0); } } +#endif //QT_NO_IM if(focus_widget) focus_widget->d_func()->setFocus_sys(); @@ -2137,12 +2131,14 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) QApplication::sendEvent(that->style(), &out); } if(focus && QApplicationPrivate::focus_widget == focus) { +#ifndef QT_NO_IM if (focus->testAttribute(Qt::WA_InputMethodEnabled)) { QInputContext *qic = focus->inputContext(); if (qic && focus->testAttribute(Qt::WA_WState_Created) && focus->isEnabled()) qic->setFocusWidget(focus); } +#endif //QT_NO_IM QFocusEvent in(QEvent::FocusIn, reason); QPointer<QWidget> that = focus; QApplication::sendEvent(focus, &in); @@ -2503,6 +2499,7 @@ void QApplication::setActiveWindow(QWidget* act) /*!internal * Helper function that returns the new focus widget, but does not set the focus reason. * Returns 0 if a new focus widget could not be found. + * Shared with QGraphicsProxyWidgetPrivate::findFocusChild() */ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next) { @@ -3646,8 +3643,13 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // walk through parents and check for gestures if (d->gestureManager) { - if (d->gestureManager->filterEvent(receiver, e)) - return true; + if (receiver->isWidgetType()) { + if (d->gestureManager->filterEvent(static_cast<QWidget *>(receiver), e)) + return true; + } else if (QGesture *gesture = qobject_cast<QGesture *>(receiver)) { + if (d->gestureManager->filterEvent(gesture, e)) + return true; + } } @@ -4172,40 +4174,41 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (wd->gestureContext.contains(type)) { allGestures.removeAt(i); gestures.append(g); - gestureEvent->setAccepted(g, false); } else { ++i; } } - if (!gestures.isEmpty()) { + if (!gestures.isEmpty()) { // we have gestures for this w QGestureEvent ge(gestures); ge.t = gestureEvent->t; ge.spont = gestureEvent->spont; ge.m_accept = wasAccepted; + ge.d_func()->accepted = gestureEvent->d_func()->accepted; res = d->notify_helper(w, &ge); gestureEvent->spont = false; eventAccepted = ge.isAccepted(); - if (res && eventAccepted) - break; - if (!eventAccepted) { - // ### two ways to ignore the event/gesture - - // if the whole event wasn't accepted, put back those - // gestures that were not accepted. - for (int i = 0; i < gestures.size(); ++i) { - QGesture *g = gestures.at(i); - if (!ge.isAccepted(g)) - allGestures.append(g); + for (int i = 0; i < gestures.size(); ++i) { + QGesture *g = gestures.at(i); + if ((res && eventAccepted) || (!eventAccepted && ge.isAccepted(g))) { + // if the gesture was accepted, mark the target widget for it + gestureEvent->d_func()->targetWidgets[g->gestureType()] = w; + gestureEvent->setAccepted(g, true); + } else if (!eventAccepted && !ge.isAccepted(g)) { + // if the gesture was explicitly ignored by the application, + // put it back so a parent can get it + allGestures.append(g); } } } - if (allGestures.isEmpty()) + if (allGestures.isEmpty()) // everything delivered break; if (w->isWindow()) break; w = w->parentWidget(); } - gestureEvent->m_accept = eventAccepted; + foreach (QGesture *g, allGestures) + gestureEvent->setAccepted(g, false); + gestureEvent->m_accept = false; // to make sure we check individual gestures } else { res = d->notify_helper(receiver, e); } @@ -5646,7 +5649,9 @@ Qt::GestureType QApplication::registerGestureRecognizer(QGestureRecognizer *reco */ void QApplication::unregisterGestureRecognizer(Qt::GestureType type) { - QGestureManager::instance()->unregisterGestureRecognizer(type); + QApplicationPrivate *d = qApp->d_func(); + if (d->gestureManager) + d->gestureManager->unregisterGestureRecognizer(type); } QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 5a8e325..5877ba4 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -288,8 +288,8 @@ public: static Qt::NavigationMode navigationMode(); #endif - Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer); - void unregisterGestureRecognizer(Qt::GestureType type); + static Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer); + static void unregisterGestureRecognizer(Qt::GestureType type); Q_SIGNALS: void lastWindowClosed(); diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 771cddc..84e0d50 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1697,15 +1697,14 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event // (actually two events; one for horizontal and one for vertical). // As a results of this, and to make sure we dont't receive duplicate events, // we try to detect when this happend by checking the 'compatibilityEvent'. - const int scrollFactor = 4 * 8; SInt32 mdelt = 0; GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); - wheel_deltaX = mdelt * scrollFactor; + wheel_deltaX = mdelt; mdelt = 0; GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); - wheel_deltaY = mdelt * scrollFactor; + wheel_deltaY = mdelt; GetEventParameter(event, kEventParamEventRef, typeEventRef, 0, sizeof(compatibilityEvent), 0, &compatibilityEvent); } else if (ekind == kEventMouseWheelMoved) { @@ -1718,31 +1717,11 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0, sizeof(axis), 0, &axis); - // The 'new' event has acceleration applied by the OS, while the old (on - // Carbon only), has not. So we introduce acceleration here to be consistent. - // The acceleration is trying to respect both pixel based and line scrolling, - // which turns out to be rather difficult. - int linesToScroll = mdelt > 0 ? 1 : -1; - static QTime t; - int elapsed = t.elapsed(); - t.restart(); - if (elapsed < 20) - linesToScroll *= 120; - else if (elapsed < 30) - linesToScroll *= 60; - else if (elapsed < 50) - linesToScroll *= 30; - else if (elapsed < 100) - linesToScroll *= 6; - else if (elapsed < 200) - linesToScroll *= 3; - else if (elapsed < 300) - linesToScroll *= 2; - + // Remove acceleration, and use either -120 or 120 as delta: if (axis == kEventMouseWheelAxisX) - wheel_deltaX = linesToScroll * 120; + wheel_deltaX = qBound(-120, int(mdelt * 10000), 120); else - wheel_deltaY = linesToScroll * 120; + wheel_deltaY = qBound(-120, int(mdelt * 10000), 120); } } @@ -2695,11 +2674,7 @@ int QApplication::keyboardInputInterval() void QApplication::setWheelScrollLines(int n) { - Q_UNUSED(n); - // On Mac, acceleration is handled by the OS. Multiplying wheel scroll - // deltas with n will not be as cross platform as one might think! So - // we choose to go native in this case (and let wheel_scroll_lines == 1). - // QApplicationPrivate::wheel_scroll_lines = n; + QApplicationPrivate::wheel_scroll_lines = n; } int QApplication::wheelScrollLines() diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 65f61e9..0fa7269 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -441,9 +441,6 @@ public: #ifdef Q_WS_MAC static bool native_modal_dialog_active; #endif -#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) - static bool inSizeMove; -#endif static void setSystemPalette(const QPalette &pal); static void setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 689429e..30bf99a 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1030,6 +1030,14 @@ QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int void qt_init(QApplicationPrivate * /* priv */, int) { if (!CCoeEnv::Static()) { + // The S60 framework creates a new trap handler which will render any existing traps + // invalid as long as it is active. This means that all code in main() that occurs after + // the QApplication construction needs to be surrounded by a new trap, despite having + // an outer one already. To avoid this, we save the original trap handler here, and set + // it back after the S60 framework is constructed. Then we restore it right before the S60 + // framework destruction. + TTrapHandler *origTrapHandler = User::TrapHandler(); + // The S60 framework has not been initalized. We need to do it. TApaApplicationFactory factory(S60->s60ApplicationFactory ? S60->s60ApplicationFactory : newS60Application); @@ -1041,6 +1049,8 @@ void qt_init(QApplicationPrivate * /* priv */, int) QT_TRAP_THROWING(coe->ConstructAppFromCommandLineL(factory,*commandLine)); delete commandLine; + S60->s60InstalledTrapHandler = User::SetTrapHandler(origTrapHandler); + S60->qtOwnsS60Environment = true; } else { S60->qtOwnsS60Environment = false; @@ -1195,6 +1205,9 @@ void qt_cleanup() S60->wsSession().SetPointerCursorMode(EPointerCursorNone); if (S60->qtOwnsS60Environment) { + // Restore the S60 framework trap handler. See qt_init(). + User::SetTrapHandler(S60->s60InstalledTrapHandler); + CEikonEnv* coe = CEikonEnv::Static(); coe->PrepareToExit(); // The CEikonEnv itself is destroyed in here. diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 5bb25fa..d98ecbb 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -615,6 +615,8 @@ static void qt_set_windows_font_resources() if (qt_wince_is_mobile()) { smallerFont.setPointSize(systemFont.pointSize()-1); QApplication::setFont(smallerFont, "QTabBar"); + smallerFont.setBold(true); + QApplication::setFont(smallerFont, "QAbstractButton"); } #endif// Q_WS_WINCE } @@ -1916,11 +1918,9 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #ifndef Q_WS_WINCE case WM_ENTERSIZEMOVE: autoCaptureWnd = hwnd; - QApplicationPrivate::inSizeMove = true; break; case WM_EXITSIZEMOVE: autoCaptureWnd = 0; - QApplicationPrivate::inSizeMove = false; break; #endif case WM_MOVE: // move window diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index bf95684..b71ae73 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -79,7 +79,7 @@ #include <private/qcolor_p.h> #include <private/qcursor_p.h> #include <private/qiconloader_p.h> -#include <private/gtksymbols_p.h> +#include <qgtkstyle.h> #include "qstyle.h" #include "qmetaobject.h" #include "qtimer.h" @@ -1625,6 +1625,7 @@ void qt_init(QApplicationPrivate *priv, int, // MIT-SHM X11->use_mitshm = false; + X11->use_mitshm_pixmaps = false; X11->mitshm_major = 0; X11->sip_serial = 0; @@ -1918,12 +1919,13 @@ void qt_init(QApplicationPrivate *priv, int, bool local = displayName.isEmpty() || displayName.lastIndexOf(QLatin1Char(':')) == 0; if (local && (qgetenv("QT_X11_NO_MITSHM").toInt() == 0)) { Visual *defaultVisual = DefaultVisual(X11->display, DefaultScreen(X11->display)); - X11->use_mitshm = mitshm_pixmaps && ((defaultVisual->red_mask == 0xff0000 - || defaultVisual->red_mask == 0xf800) - && (defaultVisual->green_mask == 0xff00 - || defaultVisual->green_mask == 0x7e0) - && (defaultVisual->blue_mask == 0xff - || defaultVisual->blue_mask == 0x1f)); + X11->use_mitshm = ((defaultVisual->red_mask == 0xff0000 + || defaultVisual->red_mask == 0xf800) + && (defaultVisual->green_mask == 0xff00 + || defaultVisual->green_mask == 0x7e0) + && (defaultVisual->blue_mask == 0xff + || defaultVisual->blue_mask == 0x1f)); + X11->use_mitshm_pixmaps = X11->use_mitshm && mitshm_pixmaps; } } #endif // QT_NO_MITSHM @@ -2297,7 +2299,7 @@ void qt_init(QApplicationPrivate *priv, int, #if !defined(QT_NO_STYLE_GTK) if (X11->desktopEnvironment == DE_GNOME) { - static bool menusHaveIcons = QGtk::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true); + static bool menusHaveIcons = QGtkStyle::getGConfBool(QLatin1String("/desktop/gnome/interface/menus_have_icons"), true); QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !menusHaveIcons); } #endif @@ -3750,6 +3752,12 @@ int QApplication::x11ProcessEvent(XEvent* event) qt_get_net_virtual_roots(); } else if (event->xproperty.atom == ATOM(_NET_WORKAREA)) { qt_desktopwidget_update_workarea(); + + // emit the workAreaResized() signal + QDesktopWidget *desktop = QApplication::desktop(); + int numScreens = desktop->numScreens(); + for (int i = 0; i < numScreens; ++i) + emit desktop->workAreaResized(i); } } else if (widget) { widget->translatePropertyEvent(event); diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index 5ed4dc9..e43f8b5 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -296,12 +296,16 @@ QString QClipboard::text(QString &subtype, Mode mode) const const QByteArray rawData = data->data(QLatin1String("text/") + subtype); +#ifndef QT_NO_TEXTCODEC QTextCodec* codec = QTextCodec::codecForMib(106); // utf-8 is default if (subtype == QLatin1String("html")) codec = QTextCodec::codecForHtml(rawData, codec); else codec = QTextCodec::codecForUtfText(rawData, codec); return codec->toUnicode(rawData); +#else //QT_NO_TEXTCODEC + return rawData; +#endif //QT_NO_TEXTCODEC } /*! diff --git a/src/gui/kernel/qclipboard_mac.cpp b/src/gui/kernel/qclipboard_mac.cpp index 3db647b..8892269 100644 --- a/src/gui/kernel/qclipboard_mac.cpp +++ b/src/gui/kernel/qclipboard_mac.cpp @@ -532,7 +532,7 @@ QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped // correctly (as '\n') in this data. The 'public.utf16-plain-text' type // usually maps newlines to '\r' instead. - QString str = qt_mac_get_pasteboardString(); + QString str = qt_mac_get_pasteboardString(paste); if (!str.isEmpty()) return str; } diff --git a/src/gui/kernel/qclipboard_win.cpp b/src/gui/kernel/qclipboard_win.cpp index 7f7ef0c..0157052 100644 --- a/src/gui/kernel/qclipboard_win.cpp +++ b/src/gui/kernel/qclipboard_win.cpp @@ -51,6 +51,7 @@ #include "qmime.h" #include "qt_windows.h" #include "qdnd_p.h" +#include <private/qwidget_p.h> QT_BEGIN_NAMESPACE @@ -140,6 +141,9 @@ public: clipBoardViewer = new QWidget(); clipBoardViewer->createWinId(); clipBoardViewer->setObjectName(QLatin1String("internal clipboard owner")); + // We dont need this internal widget to appear in QApplication::topLevelWidgets() + if (QWidgetPrivate::allWidgets) + QWidgetPrivate::allWidgets->remove(clipBoardViewer); } ~QClipboardData() diff --git a/src/gui/kernel/qclipboard_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp index 9621944..22d7c9e 100644 --- a/src/gui/kernel/qclipboard_x11.cpp +++ b/src/gui/kernel/qclipboard_x11.cpp @@ -78,6 +78,7 @@ #include "qimagewriter.h" #include "qvariant.h" #include "qdnd_p.h" +#include <private/qwidget_p.h> #ifndef QT_NO_XFIXES #include <X11/extensions/Xfixes.h> @@ -131,6 +132,11 @@ void setupOwner() requestor = new QWidget(0); requestor->createWinId(); requestor->setObjectName(QLatin1String("internal clipboard requestor")); + // We dont need this internal widgets to appear in QApplication::topLevelWidgets() + if (QWidgetPrivate::allWidgets) { + QWidgetPrivate::allWidgets->remove(owner); + QWidgetPrivate::allWidgets->remove(requestor); + } qAddPostRoutine(cleanup); } @@ -769,6 +775,9 @@ QByteArray QX11Data::clipboardReadIncrementalProperty(Window win, Atom property, delete requestor; requestor = new QWidget(0); requestor->setObjectName(QLatin1String("internal clipboard requestor")); + // We dont need this internal widget to appear in QApplication::topLevelWidgets() + if (QWidgetPrivate::allWidgets) + QWidgetPrivate::allWidgets->remove(requestor); return QByteArray(); } diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 4c2a14a..a16d1f8 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -51,6 +51,7 @@ #include <private/qmacinputcontext_p.h> #include <private/qmultitouch_mac_p.h> #include <private/qevent_p.h> +#include <private/qbackingstore_p.h> #include <qscrollarea.h> #include <qhash.h> @@ -503,6 +504,12 @@ extern "C" { - (void)drawRect:(NSRect)aRect { + if (QApplicationPrivate::graphicsSystem() != 0) { + if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) + bs->markDirty(qwidget->rect(), qwidget); + qwidgetprivate->syncBackingStore(qwidget->rect()); + return; + } CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; qwidgetprivate->hd = cg; CGContextSaveGState(cg); @@ -738,7 +745,7 @@ extern "C" { { qMacDnDParams()->view = self; qMacDnDParams()->theEvent = theEvent; - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::LeftButton); + bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); if (!mouseOK) [super mouseDragged:theEvent]; @@ -748,7 +755,7 @@ extern "C" { { qMacDnDParams()->view = self; qMacDnDParams()->theEvent = theEvent; - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::RightButton); + bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); if (!mouseOK) [super rightMouseDragged:theEvent]; @@ -758,8 +765,7 @@ extern "C" { { qMacDnDParams()->view = self; qMacDnDParams()->theEvent = theEvent; - Qt::MouseButton mouseButton = cocoaButton2QtButton([theEvent buttonNumber]); - bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, mouseButton); + bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); if (!mouseOK) [super otherMouseDragged:theEvent]; @@ -788,23 +794,23 @@ extern "C" { const EventRef carbonEvent = (EventRef)[theEvent eventRef]; const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; - if (carbonEventKind == kEventMouseScroll) { + const bool scrollEvent = carbonEventKind == kEventMouseScroll; + + if (scrollEvent) { // The mouse device containts pixel scroll wheel support (Mighty Mouse, Trackpad). // Since deviceDelta is delivered as pixels rather than degrees, we need to // convert from pixels to degrees in a sensible manner. // It looks like four degrees per pixel behaves most native. // Qt expects the unit for delta to be 1/8 of a degree: - const int scrollFactor = 4 * 8; - deltaX = (int)[theEvent deviceDeltaX] * scrollFactor; - deltaY = (int)[theEvent deviceDeltaY] * scrollFactor; - deltaZ = (int)[theEvent deviceDeltaZ] * scrollFactor; - } else { // carbonEventKind == kEventMouseWheelMoved - // Mouse wheel deltas seem to tick in at increments of 0.1. - // Qt widgets expect the delta to be a multiple of 120. - const int scrollFactor = 10 * 120; - deltaX = [theEvent deltaX] * scrollFactor; - deltaY = [theEvent deltaY] * scrollFactor; - deltaZ = [theEvent deltaZ] * scrollFactor; + deltaX = [theEvent deviceDeltaX]; + deltaY = [theEvent deviceDeltaY]; + deltaZ = [theEvent deviceDeltaZ]; + } else { + // carbonEventKind == kEventMouseWheelMoved + // Remove acceleration, and use either -120 or 120 as delta: + deltaX = qBound(-120, int([theEvent deltaX] * 10000), 120); + deltaY = qBound(-120, int([theEvent deltaY] * 10000), 120); + deltaZ = qBound(-120, int([theEvent deltaZ] * 10000), 120); } if (deltaX != 0) { diff --git a/src/gui/kernel/qdesktopwidget.cpp b/src/gui/kernel/qdesktopwidget.cpp new file mode 100644 index 0000000..c6d5000 --- /dev/null +++ b/src/gui/kernel/qdesktopwidget.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglobal.h" +#include "qdesktopwidget.h" +#include "qwidget_p.h" + +QT_BEGIN_NAMESPACE + +const QRect QDesktopWidget::screenGeometry(const QWidget *widget) const +{ + QRect rect = QWidgetPrivate::screenGeometry(widget); + if (rect.isNull()) + return screenGeometry(screenNumber(widget)); + else return rect; +} + +const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const +{ + QRect rect = QWidgetPrivate::screenGeometry(widget); + if (rect.isNull()) + return availableGeometry(screenNumber(widget)); + else + return rect; +} + +QT_END_NAMESPACE + diff --git a/src/gui/kernel/qdesktopwidget.h b/src/gui/kernel/qdesktopwidget.h index 85f479e..6e3447c 100644 --- a/src/gui/kernel/qdesktopwidget.h +++ b/src/gui/kernel/qdesktopwidget.h @@ -75,14 +75,12 @@ public: QWidget *screen(int screen = -1); const QRect screenGeometry(int screen = -1) const; - const QRect screenGeometry(const QWidget *widget) const - { return screenGeometry(screenNumber(widget)); } + const QRect screenGeometry(const QWidget *widget) const; const QRect screenGeometry(const QPoint &point) const { return screenGeometry(screenNumber(point)); } const QRect availableGeometry(int screen = -1) const; - const QRect availableGeometry(const QWidget *widget) const - { return availableGeometry(screenNumber(widget)); } + const QRect availableGeometry(const QWidget *widget) const; const QRect availableGeometry(const QPoint &point) const { return availableGeometry(screenNumber(point)); } diff --git a/src/gui/kernel/qdesktopwidget_x11.cpp b/src/gui/kernel/qdesktopwidget_x11.cpp index 02a2c82..14eb976 100644 --- a/src/gui/kernel/qdesktopwidget_x11.cpp +++ b/src/gui/kernel/qdesktopwidget_x11.cpp @@ -384,10 +384,8 @@ void QDesktopWidget::resizeEvent(QResizeEvent *event) Q_D(QDesktopWidget); int oldScreenCount = d->screenCount; QVector<QRect> oldRects(oldScreenCount); - QVector<QRect> oldWorks(oldScreenCount); for (int i = 0; i < oldScreenCount; ++i) { oldRects[i] = d->rects[i]; - oldWorks[i] = d->workareas[i]; } d->init(); @@ -397,13 +395,6 @@ void QDesktopWidget::resizeEvent(QResizeEvent *event) emit resized(i); } - // ### workareas are just reset by init, not filled with new values - // ### so this will not work correctly - for (int j = 0; j < qMin(oldScreenCount, d->screenCount); ++j) { - if (oldWorks.at(j) != d->workareas[j]) - emit workAreaResized(j); - } - if (oldScreenCount != d->screenCount) { emit screenCountChanged(d->screenCount); } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 2ff6d65..55a329c 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -45,6 +45,7 @@ #include "private/qapplication_p.h" #include "private/qkeysequence_p.h" #include "qwidget.h" +#include "qgraphicsview.h" #include "qdebug.h" #include "qmime.h" #include "qdnd_p.h" @@ -4223,8 +4224,17 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T Creates new QGestureEvent containing a list of \a gestures. */ QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures) - : QEvent(QEvent::Gesture), gestures_(gestures) + : QEvent(QEvent::Gesture) { + d = reinterpret_cast<QEventPrivate *>(new QGestureEventPrivate(gestures)); +} + +/*! + Destroys QGestureEvent. +*/ +QGestureEvent::~QGestureEvent() +{ + delete reinterpret_cast<QGestureEventPrivate *>(d); } /*! @@ -4232,7 +4242,7 @@ QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures) */ QList<QGesture *> QGestureEvent::allGestures() const { - return gestures_; + return d_func()->gestures; } /*! @@ -4240,9 +4250,10 @@ QList<QGesture *> QGestureEvent::allGestures() const */ QGesture *QGestureEvent::gesture(Qt::GestureType type) const { - for(int i = 0; i < gestures_.size(); ++i) - if (gestures_.at(i)->gestureType() == type) - return gestures_.at(i); + const QGestureEventPrivate *d = d_func(); + for(int i = 0; i < d->gestures.size(); ++i) + if (d->gestures.at(i)->gestureType() == type) + return d->gestures.at(i); return 0; } @@ -4251,7 +4262,12 @@ QGesture *QGestureEvent::gesture(Qt::GestureType type) const */ QList<QGesture *> QGestureEvent::activeGestures() const { - return gestures_; + QList<QGesture *> gestures; + foreach (QGesture *gesture, d_func()->gestures) { + if (gesture->state() != Qt::GestureCanceled) + gestures.append(gesture); + } + return gestures; } /*! @@ -4259,7 +4275,12 @@ QList<QGesture *> QGestureEvent::activeGestures() const */ QList<QGesture *> QGestureEvent::canceledGestures() const { - return gestures_; + QList<QGesture *> gestures; + foreach (QGesture *gesture, d_func()->gestures) { + if (gesture->state() == Qt::GestureCanceled) + gestures.append(gesture); + } + return gestures; } /*! @@ -4277,9 +4298,8 @@ QList<QGesture *> QGestureEvent::canceledGestures() const */ void QGestureEvent::setAccepted(QGesture *gesture, bool value) { - setAccepted(false); if (gesture) - gesture->d_func()->accept = value; + setAccepted(gesture->gestureType(), value); } /*! @@ -4293,7 +4313,8 @@ void QGestureEvent::setAccepted(QGesture *gesture, bool value) */ void QGestureEvent::accept(QGesture *gesture) { - setAccepted(gesture, true); + if (gesture) + setAccepted(gesture->gestureType(), true); } /*! @@ -4307,7 +4328,8 @@ void QGestureEvent::accept(QGesture *gesture) */ void QGestureEvent::ignore(QGesture *gesture) { - setAccepted(gesture, false); + if (gesture) + setAccepted(gesture->gestureType(), false); } /*! @@ -4315,7 +4337,117 @@ void QGestureEvent::ignore(QGesture *gesture) */ bool QGestureEvent::isAccepted(QGesture *gesture) const { - return gesture ? gesture->d_func()->accept : false; + return gesture ? isAccepted(gesture->gestureType()) : false; +} + +/*! + Sets the accept flag of the given \a gestureType object to the specified + \a value. + + Setting the accept flag indicates that the event receiver wants the \a gesture. + Unwanted gestures may be propagated to the parent widget. + + By default, gestures in events of type QEvent::Gesture are accepted, and + gestures in QEvent::GestureOverride events are ignored. + + For convenience, the accept flag can also be set with + \l{QGestureEvent::accept()}{accept(gestureType)}, and cleared with + \l{QGestureEvent::ignore()}{ignore(gestureType)}. +*/ +void QGestureEvent::setAccepted(Qt::GestureType gestureType, bool value) +{ + setAccepted(false); + d_func()->accepted[gestureType] = value; +} + +/*! + Sets the accept flag of the given \a gestureType, the equivalent of calling + \l{QGestureEvent::setAccepted()}{setAccepted(gestureType, true)}. + + Setting the accept flag indicates that the event receiver wants the + gesture. Unwanted gestures may be propagated to the parent widget. + + \sa QGestureEvent::ignore() +*/ +void QGestureEvent::accept(Qt::GestureType gestureType) +{ + setAccepted(gestureType, true); +} + +/*! + Clears the accept flag parameter of the given \a gestureType, the equivalent + of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}. + + Clearing the accept flag indicates that the event receiver does not + want the gesture. Unwanted gestures may be propgated to the parent widget. + + \sa QGestureEvent::accept() +*/ +void QGestureEvent::ignore(Qt::GestureType gestureType) +{ + setAccepted(gestureType, false); +} + +/*! + Returns true if the gesture of type \a gestureType is accepted; otherwise + returns false. +*/ +bool QGestureEvent::isAccepted(Qt::GestureType gestureType) const +{ + return d_func()->accepted.value(gestureType, true); +} + +/*! + \internal + + Sets the widget for this event to the \a widget specified. +*/ +void QGestureEvent::setWidget(QWidget *widget) +{ + d_func()->widget = widget; +} + +/*! + Returns the widget on which the event occurred. +*/ +QWidget *QGestureEvent::widget() const +{ + return d_func()->widget; +} + +#ifndef QT_NO_GRAPHICSVIEW +/*! + Returns the scene-local coordinates if the \a gesturePoint is inside a graphics view. + + \sa QPointF::isNull(). +*/ +QPointF QGestureEvent::mapToScene(const QPointF &gesturePoint) const +{ + QWidget *w = widget(); + if (w) // we get the viewport as widget, not the graphics view + w = w->parentWidget(); + QGraphicsView *view = qobject_cast<QGraphicsView*>(w); + if (view) { + return view->mapToScene(view->mapFromGlobal(gesturePoint.toPoint())); + } + return QPointF(); +} +#endif //QT_NO_GRAPHICSVIEW + +/*! + \internal +*/ +QGestureEventPrivate *QGestureEvent::d_func() +{ + return reinterpret_cast<QGestureEventPrivate *>(d); +} + +/*! + \internal +*/ +const QGestureEventPrivate *QGestureEvent::d_func() const +{ + return reinterpret_cast<const QGestureEventPrivate *>(d); } #ifdef Q_NO_USING_KEYWORD diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 3516222..141ccad 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -820,10 +820,12 @@ protected: }; class QGesture; +class QGestureEventPrivate; class Q_GUI_EXPORT QGestureEvent : public QEvent { public: QGestureEvent(const QList<QGesture *> &gestures); + ~QGestureEvent(); QList<QGesture *> allGestures() const; QGesture *gesture(Qt::GestureType type) const; @@ -849,8 +851,24 @@ public: void ignore(QGesture *); bool isAccepted(QGesture *) const; + void setAccepted(Qt::GestureType, bool); + void accept(Qt::GestureType); + void ignore(Qt::GestureType); + bool isAccepted(Qt::GestureType) const; + + void setWidget(QWidget *widget); + QWidget *widget() const; + +#ifndef QT_NO_GRAPHICSVIEW + QPointF mapToScene(const QPointF &gesturePoint) const; +#endif + private: - QList<QGesture *> gestures_; + QGestureEventPrivate *d_func(); + const QGestureEventPrivate *d_func() const; + + friend class QApplication; + friend class QGestureManager; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index c7a4975..6e6ab01 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -150,6 +150,20 @@ public: #endif }; +class QGestureEventPrivate +{ +public: + inline QGestureEventPrivate(const QList<QGesture *> &list) + : gestures(list), widget(0) + { + } + + QList<QGesture *> gestures; + QWidget *widget; + QMap<Qt::GestureType, bool> accepted; + QMap<Qt::GestureType, QWidget *> targetWidgets; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index fc8df49..850f22c 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -69,10 +69,9 @@ QT_BEGIN_NAMESPACE \section1 Lifecycle of a Gesture Object - A QGesture instance is created when the application calls QWidget::grabGesture() - or QGraphicsObject::grabGesture() to configure a widget or graphics object (the - target object) for gesture input. One gesture object is created for each target - object. + A QGesture instance is implicitly created when needed and is owned by Qt. + Developers should never destroy them or store them for later use as Qt may + destroy particular instances of them and create new ones to replace them. The registered gesture recognizer monitors the input events for the target object via its \l{QGestureRecognizer::}{filterEvent()} function, updating the @@ -129,8 +128,12 @@ QGesture::~QGesture() \brief The point that is used to find the receiver for the gesture event. - If the hot-spot is not set, the targetObject is used as the receiver of the - gesture event. + The hot-spot is a point in the global coordinate system, use + QWidget::mapFromGlobal() or QGestureEvent::mapToScene() to get a + local hot-spot. + + The hot-spot should be set by the gesture recognizer to allow gesture event + delivery to a QGraphicsObject. */ /*! @@ -138,12 +141,6 @@ QGesture::~QGesture() \brief whether the gesture has a hot-spot */ -/*! - \property QGesture::targetObject - \brief the target object which will receive the gesture event if the hotSpot is - not set -*/ - Qt::GestureType QGesture::gestureType() const { return d_func()->gestureType; @@ -154,16 +151,6 @@ Qt::GestureState QGesture::state() const return d_func()->state; } -QObject *QGesture::targetObject() const -{ - return d_func()->targetObject; -} - -void QGesture::setTargetObject(QObject *value) -{ - d_func()->targetObject = value; -} - QPointF QGesture::hotSpot() const { return d_func()->hotSpot; @@ -187,6 +174,29 @@ void QGesture::unsetHotSpot() } /*! + \enum QGesture::GestureCancelPolicy + + This enum describes how accepting a gesture can cancel other gestures + automatically. + + \value CancelNone On accepting this gesture no other gestures will be affected. + \value CancelAllInContext On accepting this gesture all gestures that are active + in the context (Qt::GestureContext) will be cancelled. +*/ + +void QGesture::setGestureCancelPolicy(GestureCancelPolicy policy) +{ + Q_D(QGesture); + d->gestureCancelPolicy = static_cast<uint>(policy); +} + +QGesture::GestureCancelPolicy QGesture::gestureCancelPolicy() const +{ + Q_D(const QGesture); + return static_cast<GestureCancelPolicy>(d->gestureCancelPolicy); +} + +/*! \class QPanGesture \since 4.6 \brief The QPanGesture class describes a panning gesture made by the user. @@ -207,6 +217,16 @@ void QGesture::unsetHotSpot() */ /*! + \property QGesture::GestureCancelPolicy + \brief the policy for deciding what happens on accepting a gesture + + On accepting one gesture Qt can automatically cancel other gestures + that belong to other targets. The policy is normally set to not cancel + any other gestures and can be set to cancel all active gestures in the + context. For example for all child widgets. +*/ + +/*! \property QPanGesture::lastOffset \brief the last offset recorded for this gesture @@ -241,17 +261,17 @@ QPanGesture::QPanGesture(QObject *parent) d_func()->gestureType = Qt::PanGesture; } -QSizeF QPanGesture::totalOffset() const +QPointF QPanGesture::totalOffset() const { return d_func()->totalOffset; } -QSizeF QPanGesture::lastOffset() const +QPointF QPanGesture::lastOffset() const { return d_func()->lastOffset; } -QSizeF QPanGesture::offset() const +QPointF QPanGesture::offset() const { return d_func()->offset; } @@ -262,17 +282,17 @@ qreal QPanGesture::acceleration() const } -void QPanGesture::setTotalOffset(const QSizeF &value) +void QPanGesture::setTotalOffset(const QPointF &value) { d_func()->totalOffset = value; } -void QPanGesture::setLastOffset(const QSizeF &value) +void QPanGesture::setLastOffset(const QPointF &value) { d_func()->lastOffset = value; } -void QPanGesture::setOffset(const QSizeF &value) +void QPanGesture::setOffset(const QPointF &value) { d_func()->offset = value; } diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index 02eb526..524d26e 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -65,9 +65,9 @@ class Q_GUI_EXPORT QGesture : public QObject Q_PROPERTY(Qt::GestureState state READ state) Q_PROPERTY(Qt::GestureType gestureType READ gestureType) + Q_PROPERTY(QGesture::GestureCancelPolicy gestureCancelPolicy READ gestureCancelPolicy WRITE setGestureCancelPolicy) Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot RESET unsetHotSpot) Q_PROPERTY(bool hasHotSpot READ hasHotSpot) - Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject) public: explicit QGesture(QObject *parent = 0); @@ -77,14 +77,19 @@ public: Qt::GestureState state() const; - QObject *targetObject() const; - void setTargetObject(QObject *value); - QPointF hotSpot() const; void setHotSpot(const QPointF &value); bool hasHotSpot() const; void unsetHotSpot(); + enum GestureCancelPolicy { + CancelNone = 0, + CancelAllInContext + }; + + void setGestureCancelPolicy(GestureCancelPolicy policy); + GestureCancelPolicy gestureCancelPolicy() const; + protected: QGesture(QGesturePrivate &dd, QObject *parent); @@ -100,22 +105,22 @@ class Q_GUI_EXPORT QPanGesture : public QGesture Q_OBJECT Q_DECLARE_PRIVATE(QPanGesture) - Q_PROPERTY(QSizeF totalOffset READ totalOffset WRITE setTotalOffset) - Q_PROPERTY(QSizeF lastOffset READ lastOffset WRITE setLastOffset) - Q_PROPERTY(QSizeF offset READ offset WRITE setOffset) + Q_PROPERTY(QPointF totalOffset READ totalOffset WRITE setTotalOffset) + Q_PROPERTY(QPointF lastOffset READ lastOffset WRITE setLastOffset) + Q_PROPERTY(QPointF offset READ offset WRITE setOffset) Q_PROPERTY(qreal acceleration READ acceleration WRITE setAcceleration) public: QPanGesture(QObject *parent = 0); - QSizeF totalOffset() const; - QSizeF lastOffset() const; - QSizeF offset() const; + QPointF totalOffset() const; + QPointF lastOffset() const; + QPointF offset() const; qreal acceleration() const; - void setTotalOffset(const QSizeF &value); - void setLastOffset(const QSizeF &value); - void setOffset(const QSizeF &value); + void setTotalOffset(const QPointF &value); + void setLastOffset(const QPointF &value); + void setOffset(const QPointF &value); void setAcceleration(qreal value); friend class QPanGestureRecognizer; @@ -212,6 +217,7 @@ public: QT_END_NAMESPACE +Q_DECLARE_METATYPE(QGesture::GestureCancelPolicy) QT_END_HEADER #endif // QGESTURE_H diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 7f69a4e..34fbb26 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -67,17 +67,17 @@ class QGesturePrivate : public QObjectPrivate public: QGesturePrivate() - : gestureType(Qt::CustomGesture), state(Qt::NoGesture), isHotSpotSet(false), - targetObject(0), accept(true) + : gestureType(Qt::CustomGesture), state(Qt::NoGesture), + isHotSpotSet(false), gestureCancelPolicy(0) + { } Qt::GestureType gestureType; Qt::GestureState state; QPointF hotSpot; - bool isHotSpotSet; - QObject *targetObject; - bool accept; + uint isHotSpotSet : 1; + uint gestureCancelPolicy : 2; }; class QPanGesturePrivate : public QGesturePrivate @@ -90,9 +90,9 @@ public: { } - QSizeF totalOffset; - QSizeF lastOffset; - QSizeF offset; + QPointF totalOffset; + QPointF lastOffset; + QPointF offset; QPoint lastPosition; qreal acceleration; }; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 0f0aef2..0a88a24 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -44,6 +44,7 @@ #include "private/qwidget_p.h" #include "private/qgesture_p.h" #include "private/qgraphicsitem_p.h" +#include "private/qevent_p.h" #include "qgesture.h" #include "qevent.h" #include "qgraphicsitem.h" @@ -64,7 +65,7 @@ QT_BEGIN_NAMESPACE QGestureManager::QGestureManager(QObject *parent) - : QObject(parent), state(NotGesture), lastCustomGestureId(0) + : QObject(parent), state(NotGesture), m_lastCustomGestureId(0) { qRegisterMetaType<Qt::GestureState>(); @@ -81,33 +82,74 @@ QGestureManager::QGestureManager(QObject *parent) QGestureManager::~QGestureManager() { - + qDeleteAll(m_recognizers.values()); + foreach (QGestureRecognizer *recognizer, m_obsoleteGestures.keys()) { + qDeleteAll(m_obsoleteGestures.value(recognizer)); + delete recognizer; + } + m_obsoleteGestures.clear(); } Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer) { QGesture *dummy = recognizer->createGesture(0); if (!dummy) { - qWarning("QGestureManager::registerGestureRecognizer: the recognizer doesn't provide gesture object"); + qWarning("QGestureManager::registerGestureRecognizer: " + "the recognizer fails to create a gesture object, skipping registration."); return Qt::GestureType(0); } Qt::GestureType type = dummy->gestureType(); if (type == Qt::CustomGesture) { // generate a new custom gesture id - ++lastCustomGestureId; - type = Qt::GestureType(Qt::CustomGesture + lastCustomGestureId); + ++m_lastCustomGestureId; + type = Qt::GestureType(Qt::CustomGesture + m_lastCustomGestureId); } - recognizers.insertMulti(type, recognizer); + m_recognizers.insertMulti(type, recognizer); delete dummy; return type; } -void QGestureManager::unregisterGestureRecognizer(Qt::GestureType) +void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) { + QList<QGestureRecognizer *> list = m_recognizers.values(type); + m_recognizers.remove(type); + foreach (QGesture *g, m_gestureToRecognizer.keys()) { + QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g); + if (list.contains(recognizer)) { + m_deletedRecognizers.insert(g, recognizer); + m_gestureToRecognizer.remove(g); + } + } + foreach (QGestureRecognizer *recognizer, list) { + QList<QGesture *> obsoleteGestures; + QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin(); + while (iter != m_objectGestures.end()) { + ObjectGesture objectGesture = iter.key(); + if (objectGesture.gesture == type) + obsoleteGestures << iter.value(); + ++iter; + } + m_obsoleteGestures.insert(recognizer, obsoleteGestures); + } } -QGesture* QGestureManager::getState(QObject *object, Qt::GestureType type) +void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type) +{ + QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin(); + while (iter != m_objectGestures.end()) { + ObjectGesture objectGesture = iter.key(); + if (objectGesture.gesture == type && target == objectGesture.object.data()) { + qDeleteAll(iter.value()); + iter = m_objectGestures.erase(iter); + } else { + ++iter; + } + } +} + +// get or create a QGesture object that will represent the state for a given object, used by the recognizer +QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recognizer, Qt::GestureType type) { // if the widget is being deleted we should be carefull and not to // create a new state, as it will create QWeakPointer which doesnt work @@ -115,28 +157,43 @@ QGesture* QGestureManager::getState(QObject *object, Qt::GestureType type) if (object->isWidgetType()) { if (static_cast<QWidget *>(object)->d_func()->data.in_destructor) return 0; + } else if (QGesture *g = qobject_cast<QGesture *>(object)) { + return g; + } else { + Q_ASSERT(qobject_cast<QGraphicsObject *>(object)); } - QWeakPointer<QGesture> state = objectGestures.value(QGestureManager::ObjectGesture(object, type)); - if (!state) { - QGestureRecognizer *recognizer = recognizers.value(type); - if (recognizer) { - state = recognizer->createGesture(object); - if (!state) - return 0; - if (state.data()->gestureType() == Qt::CustomGesture) { - // if the recognizer didn't fill in the gesture type, then this - // is a custom gesture with autogenerated it and we fill it. - state.data()->d_func()->gestureType = type; - } - objectGestures.insert(QGestureManager::ObjectGesture(object, type), state); - gestureToRecognizer[state.data()] = recognizer; - } + QList<QGesture *> states = + m_objectGestures.value(QGestureManager::ObjectGesture(object, type)); + // check if the QGesture for this recognizer has already been created + foreach (QGesture *state, states) { + if (m_gestureToRecognizer.value(state) == recognizer) + return state; + } + + Q_ASSERT(recognizer); + QGesture *state = recognizer->createGesture(object); + if (!state) + return 0; + state->setParent(this); + if (state->gestureType() == Qt::CustomGesture) { + // if the recognizer didn't fill in the gesture type, then this + // is a custom gesture with autogenerated id and we fill it. + state->d_func()->gestureType = type; +#if defined(GESTURE_DEBUG) + state->setObjectName(QString::number((int)type)); +#endif } - return state.data(); + m_objectGestures[QGestureManager::ObjectGesture(object, type)].append(state); + m_gestureToRecognizer[state] = recognizer; + m_gestureOwners[state] = object; + + return state; } -bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) +bool QGestureManager::filterEventThroughContexts(const QMultiHash<QObject *, + Qt::GestureType> &contexts, + QEvent *event) { QSet<QGesture *> triggeredGestures; QSet<QGesture *> finishedGestures; @@ -144,140 +201,79 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) QSet<QGesture *> canceledGestures; QSet<QGesture *> notGestures; - QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(receiver); - if (receiver->isWidgetType() || graphicsObject) { - QMap<QObject *, Qt::GestureType> contexts; - if (receiver->isWidgetType()) { - QWidget *w = static_cast<QWidget *>(receiver); - if (!w->d_func()->gestureContext.isEmpty()) { - typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; - for(ContextIterator it = w->d_func()->gestureContext.begin(), - e = w->d_func()->gestureContext.end(); it != e; ++it) { - contexts.insertMulti(w, it.key()); - } - } - // find all gesture contexts for the widget tree - w = w->parentWidget(); - while (w) - { - typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; - for (ContextIterator it = w->d_func()->gestureContext.begin(), - e = w->d_func()->gestureContext.end(); it != e; ++it) { - if (it.value() == Qt::WidgetWithChildrenGesture) - contexts.insertMulti(w, it.key()); - } - w = w->parentWidget(); - } - } else { - QGraphicsObject *item = graphicsObject; - if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) { - typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; - for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(), - e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { - contexts.insertMulti(item, it.key()); - } - } - // find all gesture contexts for the widget tree - item = item->parentObject(); - while (item) - { - typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; - for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(), - e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { - if (it.value() == Qt::WidgetWithChildrenGesture) - contexts.insertMulti(item, it.key()); - } - item = item->parentObject(); - } - } - // filter the event through recognizers - typedef QMap<QObject *, Qt::GestureType>::const_iterator ContextIterator; - for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) { - Qt::GestureType gestureType = cit.value(); - QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator - rit = recognizers.lowerBound(gestureType), - re = recognizers.upperBound(gestureType); - for (; rit != re; ++rit) { - QGestureRecognizer *recognizer = rit.value(); - QObject *target = cit.key(); - QGesture *state = getState(target, gestureType); - if (!state) - continue; - QGestureRecognizer::Result result = recognizer->filterEvent(state, target, event); - QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask; - if (type == QGestureRecognizer::GestureTriggered) { - DEBUG() << "QGestureManager: gesture triggered: " << state; - triggeredGestures << state; - } else if (type == QGestureRecognizer::GestureFinished) { - DEBUG() << "QGestureManager: gesture finished: " << state; - finishedGestures << state; - } else if (type == QGestureRecognizer::MaybeGesture) { - DEBUG() << "QGestureManager: maybe gesture: " << state; - newMaybeGestures << state; - } else if (type == QGestureRecognizer::NotGesture) { - DEBUG() << "QGestureManager: not gesture: " << state; - notGestures << state; - } else if (type == QGestureRecognizer::Ignore) { - DEBUG() << "QGestureManager: gesture ignored the event: " << state; - } else { - DEBUG() << "QGestureManager: hm, lets assume the recognizer ignored the event: " << state; - } - if (result & QGestureRecognizer::ConsumeEventHint) { - DEBUG() << "QGestureManager: we were asked to consume the event: " << state; - //TODO: consume events if asked - } - } - } - } else if (QGesture *state = qobject_cast<QGesture*>(receiver)) { - if (QGestureRecognizer *recognizer = gestureToRecognizer.value(state)) { - QGestureRecognizer::Result result = recognizer->filterEvent(state, state, event); + // TODO: sort contexts by the gesture type and check if one of the contexts + // is already active. + + bool ret = false; + + // filter the event through recognizers + typedef QHash<QObject *, Qt::GestureType>::const_iterator ContextIterator; + for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) { + Qt::GestureType gestureType = cit.value(); + QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator + rit = m_recognizers.lowerBound(gestureType), + re = m_recognizers.upperBound(gestureType); + for (; rit != re; ++rit) { + QGestureRecognizer *recognizer = rit.value(); + QObject *target = cit.key(); + QGesture *state = getState(target, recognizer, gestureType); + if (!state) + continue; + QGestureRecognizer::Result result = recognizer->filterEvent(state, target, event); QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask; if (type == QGestureRecognizer::GestureTriggered) { - DEBUG() << "QGestureManager: gesture triggered: " << state; + DEBUG() << "QGestureManager:Recognizer: gesture triggered: " << state; triggeredGestures << state; } else if (type == QGestureRecognizer::GestureFinished) { - DEBUG() << "QGestureManager: gesture finished: " << state; + DEBUG() << "QGestureManager:Recognizer: gesture finished: " << state; finishedGestures << state; } else if (type == QGestureRecognizer::MaybeGesture) { - DEBUG() << "QGestureManager: maybe gesture: " << state; + DEBUG() << "QGestureManager:Recognizer: maybe gesture: " << state; newMaybeGestures << state; } else if (type == QGestureRecognizer::NotGesture) { - DEBUG() << "QGestureManager: not gesture: " << state; + DEBUG() << "QGestureManager:Recognizer: not gesture: " << state; notGestures << state; } else if (type == QGestureRecognizer::Ignore) { - DEBUG() << "QGestureManager: gesture ignored the event: " << state; + DEBUG() << "QGestureManager:Recognizer: ignored the event: " << state; } else { - DEBUG() << "QGestureManager: hm, lets assume the recognizer ignored the event: " << state; + DEBUG() << "QGestureManager:Recognizer: hm, lets assume the recognizer" + << "ignored the event: " << state; + } + if (result & QGestureRecognizer::ConsumeEventHint) { + DEBUG() << "QGestureManager: we were asked to consume the event: " + << state; + ret = true; } } - } else { - return false; } - QSet<QGesture *> startedGestures = triggeredGestures - activeGestures; - triggeredGestures &= activeGestures; + QSet<QGesture *> startedGestures = triggeredGestures - m_activeGestures; + triggeredGestures &= m_activeGestures; // check if a running gesture switched back to maybe state - QSet<QGesture *> activeToMaybeGestures = activeGestures & newMaybeGestures; + QSet<QGesture *> activeToMaybeGestures = m_activeGestures & newMaybeGestures; - // check if a running gesture switched back to not gesture state, i.e. were canceled - QSet<QGesture *> activeToCancelGestures = activeGestures & notGestures; + // check if a running gesture switched back to not gesture state, + // i.e. were canceled + QSet<QGesture *> activeToCancelGestures = m_activeGestures & notGestures; canceledGestures += activeToCancelGestures; // start timers for new gestures in maybe state foreach (QGesture *state, newMaybeGestures) { - QBasicTimer &timer = maybeGestures[state]; + QBasicTimer &timer = m_maybeGestures[state]; if (!timer.isActive()) timer.start(3000, this); } // kill timers for gestures that were in maybe state - QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures | finishedGestures | canceledGestures | notGestures); + QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures + | finishedGestures | canceledGestures + | notGestures); foreach(QGesture *gesture, notMaybeGestures) { - QMap<QGesture *, QBasicTimer>::iterator it = - maybeGestures.find(gesture); - if (it != maybeGestures.end()) { + QHash<QGesture *, QBasicTimer>::iterator it = + m_maybeGestures.find(gesture); + if (it != m_maybeGestures.end()) { it.value().stop(); - maybeGestures.erase(it); + m_maybeGestures.erase(it); } } @@ -288,21 +284,23 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) Q_ASSERT((finishedGestures & canceledGestures).isEmpty()); Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty()); - QSet<QGesture *> notStarted = finishedGestures - activeGestures; + QSet<QGesture *> notStarted = finishedGestures - m_activeGestures; if (!notStarted.isEmpty()) { // there are some gestures that claim to be finished, but never started. // probably those are "singleshot" gestures so we'll fake the started state. foreach (QGesture *gesture, notStarted) gesture->d_func()->state = Qt::GestureStarted; - deliverEvents(notStarted, receiver); + QSet<QGesture *> undeliveredGestures; + deliverEvents(notStarted, &undeliveredGestures); + finishedGestures -= undeliveredGestures; } - activeGestures += startedGestures; + m_activeGestures += startedGestures; // sanity check: all triggered gestures should already be in active gestures list - Q_ASSERT((activeGestures & triggeredGestures).size() == triggeredGestures.size()); - activeGestures -= finishedGestures; - activeGestures -= activeToMaybeGestures; - activeGestures -= canceledGestures; + Q_ASSERT((m_activeGestures & triggeredGestures).size() == triggeredGestures.size()); + m_activeGestures -= finishedGestures; + m_activeGestures -= activeToMaybeGestures; + m_activeGestures -= canceledGestures; // set the proper gesture state on each gesture foreach (QGesture *gesture, startedGestures) @@ -316,125 +314,342 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) foreach (QGesture *gesture, activeToMaybeGestures) gesture->d_func()->state = Qt::GestureFinished; - if (!activeGestures.isEmpty() || !maybeGestures.isEmpty() || + if (!m_activeGestures.isEmpty() || !m_maybeGestures.isEmpty() || !startedGestures.isEmpty() || !triggeredGestures.isEmpty() || !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) { - DEBUG() << "QGestureManager::filterEvent:" - << "\n\tactiveGestures:" << activeGestures - << "\n\tmaybeGestures:" << maybeGestures.keys() + DEBUG() << "QGestureManager::filterEventThroughContexts:" + << "\n\tactiveGestures:" << m_activeGestures + << "\n\tmaybeGestures:" << m_maybeGestures.keys() << "\n\tstarted:" << startedGestures << "\n\ttriggered:" << triggeredGestures << "\n\tfinished:" << finishedGestures << "\n\tcanceled:" << canceledGestures; } - deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures, receiver); + QSet<QGesture *> undeliveredGestures; + deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures, + &undeliveredGestures); + + foreach (QGesture *g, startedGestures) { + if (undeliveredGestures.contains(g)) + continue; + if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) { + DEBUG() << "lets try to cancel some"; + // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them + cancelGesturesForChildren(g); + } + } + + m_activeGestures -= undeliveredGestures; // reset gestures that ended - QSet<QGesture *> endedGestures = finishedGestures + canceledGestures; + QSet<QGesture *> endedGestures = + finishedGestures + canceledGestures + undeliveredGestures; foreach (QGesture *gesture, endedGestures) { - if (QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0)) { + if (QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0)) { + gesture->setGestureCancelPolicy(QGesture::CancelNone); recognizer->reset(gesture); + } else { + cleanupGesturesForRemovedRecognizer(gesture); + } + m_gestureTargets.remove(gesture); + } + return ret; +} + +// Cancel all gestures of children of the widget that original is associated with +void QGestureManager::cancelGesturesForChildren(QGesture *original) +{ + Q_ASSERT(original); + QWidget *originatingWidget = m_gestureTargets.value(original); + Q_ASSERT(originatingWidget); + + // iterate over all active gestures and all maybe gestures + // for each find the owner + // if the owner is part of our sub-hierarchy, cancel it. + + QSet<QGesture*> cancelledGestures; + QSet<QGesture*>::Iterator iter = m_activeGestures.begin(); + while (iter != m_activeGestures.end()) { + QWidget *widget = m_gestureTargets.value(*iter); + // note that we don't touch the gestures for our originatingWidget + if (widget != originatingWidget && originatingWidget->isAncestorOf(widget)) { + DEBUG() << " found a gesture to cancel" << (*iter); + (*iter)->d_func()->state = Qt::GestureCanceled; + cancelledGestures << *iter; + iter = m_activeGestures.erase(iter); + } else { + ++iter; + } + } + + // TODO handle 'maybe' gestures too + + // sort them per target widget by cherry picking from almostCanceledGestures and delivering + QSet<QGesture *> almostCanceledGestures = cancelledGestures; + while (!almostCanceledGestures.isEmpty()) { + QWidget *target = 0; + QSet<QGesture*> gestures; + iter = almostCanceledGestures.begin(); + // sort per target widget + while (iter != almostCanceledGestures.end()) { + QWidget *widget = m_gestureTargets.value(*iter); + if (target == 0) + target = widget; + if (target == widget) { + gestures << *iter; + iter = almostCanceledGestures.erase(iter); + } else { + ++iter; + } + } + Q_ASSERT(target); + + QSet<QGesture*> undeliveredGestures; + deliverEvents(gestures, &undeliveredGestures); + } + + for (iter = cancelledGestures.begin(); iter != cancelledGestures.end(); ++iter) { + QGestureRecognizer *recognizer = m_gestureToRecognizer.value(*iter, 0); + if (recognizer) { + (*iter)->setGestureCancelPolicy(QGesture::CancelNone); + recognizer->reset(*iter); + } else { + cleanupGesturesForRemovedRecognizer(*iter); + } + } +} + +void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture) +{ + QGestureRecognizer *recognizer = m_deletedRecognizers.value(gesture); + Q_ASSERT(recognizer); + m_deletedRecognizers.remove(gesture); + if (m_deletedRecognizers.keys(recognizer).isEmpty()) { + // no more active gestures, cleanup! + qDeleteAll(m_obsoleteGestures.value(recognizer)); + m_obsoleteGestures.remove(recognizer); + delete recognizer; + } +} + +// return true if accepted (consumed) +bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) +{ + QSet<Qt::GestureType> types; + QMultiHash<QObject *, Qt::GestureType> contexts; + QWidget *w = receiver; + typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; + if (!w->d_func()->gestureContext.isEmpty()) { + for(ContextIterator it = w->d_func()->gestureContext.begin(), + e = w->d_func()->gestureContext.end(); it != e; ++it) { + types.insert(it.key()); + contexts.insertMulti(w, it.key()); + } + } + // find all gesture contexts for the widget tree + w = w->isWindow() ? 0 : w->parentWidget(); + while (w) + { + for (ContextIterator it = w->d_func()->gestureContext.begin(), + e = w->d_func()->gestureContext.end(); it != e; ++it) { + if (it.value() == Qt::WidgetWithChildrenGesture) { + if (!types.contains(it.key())) { + types.insert(it.key()); + contexts.insertMulti(w, it.key()); + } + } } - gestureTargets.remove(gesture); + if (w->isWindow()) + break; + w = w->parentWidget(); } - return false; + return filterEventThroughContexts(contexts, event); } -void QGestureManager::deliverEvents(const QSet<QGesture*> &gestures, QObject *lastReceiver) +#ifndef QT_NO_GRAPHICSVIEW +bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event) +{ + QSet<Qt::GestureType> types; + QMultiHash<QObject *, Qt::GestureType> contexts; + QGraphicsObject *item = receiver; + if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) { + typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; + for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(), + e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { + types.insert(it.key()); + contexts.insertMulti(item, it.key()); + } + } + // find all gesture contexts for the graphics object tree + item = item->parentObject(); + while (item) + { + typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; + for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(), + e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { + if (it.value() == Qt::ItemWithChildrenGesture) { + if (!types.contains(it.key())) { + types.insert(it.key()); + contexts.insertMulti(item, it.key()); + } + } + } + item = item->parentObject(); + } + return filterEventThroughContexts(contexts, event); +} +#endif + +bool QGestureManager::filterEvent(QGesture *state, QEvent *event) +{ + QMultiHash<QObject *, Qt::GestureType> contexts; + contexts.insert(state, state->gestureType()); + return filterEventThroughContexts(contexts, event); +} + +void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures, + QMap<QWidget *, QList<QGesture *> > *conflicts, + QMap<QWidget *, QList<QGesture *> > *normal) +{ + typedef QHash<Qt::GestureType, QHash<QWidget *, QGesture *> > GestureByTypes; + GestureByTypes gestureByTypes; + + // sort gestures by types + foreach (QGesture *gesture, gestures) { + QWidget *receiver = m_gestureTargets.value(gesture, 0); + Q_ASSERT(receiver); + gestureByTypes[gesture->gestureType()].insert(receiver, gesture); + } + + // for each gesture type + foreach (Qt::GestureType type, gestureByTypes.keys()) { + QHash<QWidget *, QGesture *> gestures = gestureByTypes.value(type); + foreach (QWidget *widget, gestures.keys()) { + QWidget *w = widget->parentWidget(); + while (w) { + QMap<Qt::GestureType, Qt::GestureContext>::const_iterator it + = w->d_func()->gestureContext.find(type); + if (it != w->d_func()->gestureContext.end()) { + // i.e. 'w' listens to gesture 'type' + Qt::GestureContext context = it.value(); + if (context == Qt::WidgetWithChildrenGesture && w != widget) { + // conflicting gesture! + (*conflicts)[widget].append(gestures[widget]); + break; + } + } + if (w->isWindow()) { + w = 0; + break; + } + w = w->parentWidget(); + } + if (!w) + (*normal)[widget].append(gestures[widget]); + } + } +} + +void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, + QSet<QGesture *> *undeliveredGestures) { if (gestures.isEmpty()) return; - // group gestures by widgets - typedef QMap<QObject *, QList<QGesture *> > GesturesPerReceiver; - GesturesPerReceiver groupedGestures; - // for conflicted gestures the key is always the innermost widget (i.e. the child) - GesturesPerReceiver conflictedGestures; - QMultiHash<QObject *, QGesture *> objectGestures; + typedef QMap<QWidget *, QList<QGesture *> > GesturesPerWidget; + GesturesPerWidget conflictedGestures; + GesturesPerWidget normalStartedGestures; - foreach (QGesture *gesture, gestures) { - QObject *target = gestureTargets.value(gesture, 0); + QSet<QGesture *> startedGestures; + // first figure out the initial receivers of gestures + for (QSet<QGesture *>::const_iterator it = gestures.begin(), + e = gestures.end(); it != e; ++it) { + QGesture *gesture = *it; + QWidget *target = m_gestureTargets.value(gesture, 0); if (!target) { + // the gesture has just started and doesn't have a target yet. Q_ASSERT(gesture->state() == Qt::GestureStarted); if (gesture->hasHotSpot()) { - // guess the target using the hotspot of the gesture + // guess the target widget using the hotspot of the gesture QPoint pt = gesture->hotSpot().toPoint(); - if (!pt.isNull()) { - if (QWidget *w = qApp->topLevelAt(pt)) - target = w->childAt(w->mapFromGlobal(pt)); + if (QWidget *w = qApp->topLevelAt(pt)) { + target = w->childAt(w->mapFromGlobal(pt)); } + } else { + // or use the context of the gesture + QObject *context = m_gestureOwners.value(gesture, 0); + if (context->isWidgetType()) + target = static_cast<QWidget *>(context); } - if (!target) { - target = gesture->targetObject(); - if (!target) - target = lastReceiver; - } + if (target) + m_gestureTargets.insert(gesture, target); } + + Qt::GestureType gestureType = gesture->gestureType(); + Q_ASSERT(gestureType != Qt::CustomGesture); + if (target) { - gestureTargets.insert(gesture, target); - if (target->isWidgetType()) - objectGestures.insert(target, gesture); - groupedGestures[target].append(gesture); + if (gesture->state() == Qt::GestureStarted) { + startedGestures.insert(gesture); + } else { + normalStartedGestures[target].append(gesture); + } } else { - qWarning() << "QGestureManager::deliverEvent: could not find the target for gesture" + DEBUG() << "QGestureManager::deliverEvent: could not find the target for gesture" << gesture->gestureType(); + qWarning("QGestureManager::deliverEvent: could not find the target for gesture"); + undeliveredGestures->insert(gesture); } } - typedef QMultiHash<QObject *, QGesture *>::const_iterator ObjectGesturesIterator; - for (ObjectGesturesIterator it = objectGestures.begin(), e = objectGestures.end(); it != e; ++it) { - QObject *object1 = it.key(); - QWidget *widget1 = qobject_cast<QWidget *>(object1); - QGraphicsObject *item1 = qobject_cast<QGraphicsObject *>(object1); - QGesture *gesture1 = it.value(); - ObjectGesturesIterator cit = it; - for (++cit; cit != e; ++cit) { - QObject *object2 = cit.key(); - QWidget *widget2 = qobject_cast<QWidget *>(object2); - QGraphicsObject *item2 = qobject_cast<QGraphicsObject *>(object2); - QGesture *gesture2 = cit.value(); - // TODO: ugly, rewrite this. - if ((widget1 && widget2 && widget2->isAncestorOf(widget1)) || - (item1 && item2 && item2->isAncestorOf(item1))) { - groupedGestures[object2].removeOne(gesture2); - groupedGestures[object1].removeOne(gesture1); - conflictedGestures[object1].append(gesture1); - } else if ((widget1 && widget2 && widget1->isAncestorOf(widget2)) || - (item1 && item2 && item1->isAncestorOf(item2))) { - groupedGestures[object2].removeOne(gesture2); - groupedGestures[object1].removeOne(gesture1); - conflictedGestures[object2].append(gesture2); - } - } - } - - DEBUG() << "deliverEvents: conflicted =" << conflictedGestures.values() - << " grouped =" << groupedGestures.values(); + getGestureTargets(startedGestures, &conflictedGestures, &normalStartedGestures); + DEBUG() << "QGestureManager::deliverEvents:" + << "\nstarted: " << startedGestures + << "\nconflicted: " << conflictedGestures + << "\nnormal: " << normalStartedGestures + << "\n"; // if there are conflicting gestures, send the GestureOverride event - for (GesturesPerReceiver::const_iterator it = conflictedGestures.begin(), + for (GesturesPerWidget::const_iterator it = conflictedGestures.begin(), e = conflictedGestures.end(); it != e; ++it) { + QWidget *receiver = it.key(); + QList<QGesture *> gestures = it.value(); DEBUG() << "QGestureManager::deliverEvents: sending GestureOverride to" - << it.key() - << " gestures:" << it.value(); - QGestureEvent event(it.value()); + << receiver + << "gestures:" << gestures; + QGestureEvent event(gestures); event.t = QEvent::GestureOverride; + // mark event and individual gestures as ignored event.ignore(); - QApplication::sendEvent(it.key(), &event); - if (!event.isAccepted()) { - // nobody accepted the GestureOverride, put it back to deliver to - // the closest context (i.e. to the inner-most widget). - DEBUG() <<" override was not accepted"; - groupedGestures[it.key()].append(it.value()); + foreach(QGesture *g, gestures) + event.setAccepted(g, false); + + QApplication::sendEvent(receiver, &event); + bool eventAccepted = event.isAccepted(); + foreach(QGesture *gesture, event.allGestures()) { + if (eventAccepted || event.isAccepted(gesture)) { + QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0); + Q_ASSERT(w); + DEBUG() << "override event: gesture was accepted:" << gesture << w; + QList<QGesture *> &gestures = normalStartedGestures[w]; + gestures.append(gesture); + // override the target + m_gestureTargets[gesture] = w; + } else { + DEBUG() << "override event: gesture wasn't accepted. putting back:" << gesture; + QList<QGesture *> &gestures = normalStartedGestures[receiver]; + gestures.append(gesture); + } } } - for (GesturesPerReceiver::const_iterator it = groupedGestures.begin(), - e = groupedGestures.end(); it != e; ++it) { + // delivering gestures that are not in conflicted state + for (GesturesPerWidget::const_iterator it = normalStartedGestures.begin(), + e = normalStartedGestures.end(); it != e; ++it) { if (!it.value().isEmpty()) { DEBUG() << "QGestureManager::deliverEvents: sending to" << it.key() - << " gestures:" << it.value(); + << "gestures:" << it.value(); QGestureEvent event(it.value()); QApplication::sendEvent(it.key(), &event); } @@ -443,19 +658,24 @@ void QGestureManager::deliverEvents(const QSet<QGesture*> &gestures, QObject *la void QGestureManager::timerEvent(QTimerEvent *event) { - QMap<QGesture*, QBasicTimer>::iterator it = maybeGestures.begin(), - e = maybeGestures.end(); + QHash<QGesture *, QBasicTimer>::iterator it = m_maybeGestures.begin(), + e = m_maybeGestures.end(); for (; it != e; ) { QBasicTimer &timer = it.value(); Q_ASSERT(timer.isActive()); if (timer.timerId() == event->timerId()) { timer.stop(); QGesture *gesture = it.key(); - it = maybeGestures.erase(it); - DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" << gesture; - QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0); - if (recognizer) + it = m_maybeGestures.erase(it); + DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" + << gesture; + QGestureRecognizer *recognizer = m_gestureToRecognizer.value(gesture, 0); + if (recognizer) { + gesture->setGestureCancelPolicy(QGesture::CancelNone); recognizer->reset(gesture); + } else { + cleanupGesturesForRemovedRecognizer(gesture); + } } else { ++it; } diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index c61819f..1e0734b 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QBasicTimer; +class QGraphicsObject; class QGestureManager : public QObject { Q_OBJECT @@ -71,19 +72,27 @@ public: Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer); void unregisterGestureRecognizer(Qt::GestureType type); - bool filterEvent(QObject *receiver, QEvent *event); + bool filterEvent(QWidget *receiver, QEvent *event); + bool filterEvent(QGesture *receiver, QEvent *event); +#ifndef QT_NO_GRAPHICSVIEW + bool filterEvent(QGraphicsObject *receiver, QEvent *event); +#endif //QT_NO_GRAPHICSVIEW // declared in qapplication.cpp static QGestureManager* instance(); + void cleanupCachedGestures(QObject *target, Qt::GestureType type); + protected: void timerEvent(QTimerEvent *event); + bool filterEventThroughContexts(const QMultiHash<QObject *, Qt::GestureType> &contexts, + QEvent *event); private: - QMultiMap<Qt::GestureType, QGestureRecognizer *> recognizers; + QMultiMap<Qt::GestureType, QGestureRecognizer *> m_recognizers; - QSet<QGesture *> activeGestures; - QMap<QGesture *, QBasicTimer> maybeGestures; + QSet<QGesture *> m_activeGestures; + QHash<QGesture *, QBasicTimer> m_maybeGestures; enum State { Gesture, @@ -99,7 +108,7 @@ private: Qt::GestureType gesture; ObjectGesture(QObject *o, const Qt::GestureType &g) : object(o), gesture(g) { } - inline bool operator<(const ObjectGesture& rhs) const + inline bool operator<(const ObjectGesture &rhs) const { if (object.data() < rhs.object.data()) return true; @@ -109,15 +118,27 @@ private: } }; - QMap<ObjectGesture, QWeakPointer<QGesture> > objectGestures; - QMap<QGesture *, QGestureRecognizer *> gestureToRecognizer; + QMap<ObjectGesture, QList<QGesture *> > m_objectGestures; + QHash<QGesture *, QGestureRecognizer *> m_gestureToRecognizer; + QHash<QGesture *, QObject *> m_gestureOwners; + + QHash<QGesture *, QWidget *> m_gestureTargets; + + int m_lastCustomGestureId; - QHash<QGesture *, QObject *> gestureTargets; + QHash<QGestureRecognizer *, QList<QGesture *> > m_obsoleteGestures; + QHash<QGesture *, QGestureRecognizer *> m_deletedRecognizers; + void cleanupGesturesForRemovedRecognizer(QGesture *gesture); - int lastCustomGestureId; + QGesture *getState(QObject *widget, QGestureRecognizer *recognizer, + Qt::GestureType gesture); + void deliverEvents(const QSet<QGesture *> &gestures, + QSet<QGesture *> *undeliveredGestures); + void getGestureTargets(const QSet<QGesture*> &gestures, + QMap<QWidget *, QList<QGesture *> > *conflicts, + QMap<QWidget *, QList<QGesture *> > *normal); - QGesture *getState(QObject *widget, Qt::GestureType gesture); - void deliverEvents(const QSet<QGesture *> &gestures, QObject *lastReceiver); + void cancelGesturesForChildren(QGesture *originatingGesture); }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp index 9de3bcc..2673be3 100644 --- a/src/gui/kernel/qgesturerecognizer.cpp +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -100,7 +100,7 @@ QT_BEGIN_NAMESPACE */ /*! - \enum QGestureRecognizer::ResultFlags + \enum QGestureRecognizer::ResultFlag This enum describes the result of the current event filtering step in a gesture recognizer state machine. @@ -178,7 +178,7 @@ void QGestureRecognizer::reset(QGesture *gesture) QGesturePrivate *d = gesture->d_func(); d->state = Qt::NoGesture; d->hotSpot = QPointF(); - d->targetObject = 0; + d->isHotSpotSet = false; } } @@ -186,7 +186,7 @@ void QGestureRecognizer::reset(QGesture *gesture) \fn QGestureRecognizer::filterEvent(QGesture *gesture, QObject *watched, QEvent *event) Handles the given \a event for the \a watched object, updating the state of the \a gesture - object as required, and returns a suitable Result for the current recognition step. + object as required, and returns a suitable result for the current recognition step. This function is called by the framework to allow the recognizer to filter input events dispatched to QWidget or QGraphicsObject instances that it is monitoring. diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index efd8565..a3c990d 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -56,7 +56,7 @@ class QGesture; class Q_GUI_EXPORT QGestureRecognizer { public: - enum ResultFlags + enum ResultFlag { Ignore = 0x0001, NotGesture = 0x0002, @@ -73,7 +73,7 @@ public: ResultHint_Mask = 0xff00 }; - Q_DECLARE_FLAGS(Result, ResultFlags) + Q_DECLARE_FLAGS(Result, ResultFlag) QGestureRecognizer(); virtual ~QGestureRecognizer(); diff --git a/src/gui/kernel/qguiplatformplugin.cpp b/src/gui/kernel/qguiplatformplugin.cpp index 6e074a1..e6efec1 100644 --- a/src/gui/kernel/qguiplatformplugin.cpp +++ b/src/gui/kernel/qguiplatformplugin.cpp @@ -59,9 +59,9 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp #if defined(Q_WS_X11) -#include "qkde_p.h" -#include "qt_x11_p.h" -#include <private/gtksymbols_p.h> +#include <private/qkde_p.h> +#include <private/qgtkstyle_p.h> +#include <private/qt_x11_p.h> #endif @@ -206,7 +206,7 @@ QString QGuiPlatformPlugin::systemIconThemeName() if (X11->desktopEnvironment == DE_GNOME) { result = QString::fromLatin1("gnome"); #ifndef QT_NO_STYLE_GTK - result = QGtk::getGConfString(QLatin1String("/desktop/gnome/interface/icon_theme"), result); + result = QGtkStylePrivate::getGConfString(QLatin1String("/desktop/gnome/interface/icon_theme"), result); #endif } else if (X11->desktopEnvironment == DE_KDE) { result = X11->desktopVersion >= 4 ? QString::fromLatin1("oxygen") : QString::fromLatin1("crystalsvg"); @@ -288,6 +288,8 @@ int QGuiPlatformPlugin::platformHint(PlatformHint hint) #endif //by default keep ret = 0 so QCommonStyle will use the style default break; + default: + break; } return ret; } diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp index 0ce77fe..8164589 100644 --- a/src/gui/kernel/qkeymapper_x11.cpp +++ b/src/gui/kernel/qkeymapper_x11.cpp @@ -714,47 +714,144 @@ extern bool qt_sm_blockUserInput; #define XK_KP_Delete 0xFF9F #endif -// the next lines are taken from XFree > 4.0 (X11/XF86keysyms.h), defining some special +// the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special // multimedia keys. They are included here as not every system has them. -#define XF86XK_Standby 0x1008FF10 -#define XF86XK_AudioLowerVolume 0x1008FF11 -#define XF86XK_AudioMute 0x1008FF12 -#define XF86XK_AudioRaiseVolume 0x1008FF13 -#define XF86XK_AudioPlay 0x1008FF14 -#define XF86XK_AudioStop 0x1008FF15 -#define XF86XK_AudioPrev 0x1008FF16 -#define XF86XK_AudioNext 0x1008FF17 -#define XF86XK_HomePage 0x1008FF18 -#define XF86XK_Calculator 0x1008FF1D -#define XF86XK_Mail 0x1008FF19 -#define XF86XK_Start 0x1008FF1A -#define XF86XK_Search 0x1008FF1B -#define XF86XK_AudioRecord 0x1008FF1C -#define XF86XK_Back 0x1008FF26 -#define XF86XK_Forward 0x1008FF27 -#define XF86XK_Stop 0x1008FF28 -#define XF86XK_Refresh 0x1008FF29 -#define XF86XK_Favorites 0x1008FF30 -#define XF86XK_AudioPause 0x1008FF31 -#define XF86XK_AudioMedia 0x1008FF32 -#define XF86XK_MyComputer 0x1008FF33 -#define XF86XK_OpenURL 0x1008FF38 -#define XF86XK_Launch0 0x1008FF40 -#define XF86XK_Launch1 0x1008FF41 -#define XF86XK_Launch2 0x1008FF42 -#define XF86XK_Launch3 0x1008FF43 -#define XF86XK_Launch4 0x1008FF44 -#define XF86XK_Launch5 0x1008FF45 -#define XF86XK_Launch6 0x1008FF46 -#define XF86XK_Launch7 0x1008FF47 -#define XF86XK_Launch8 0x1008FF48 -#define XF86XK_Launch9 0x1008FF49 -#define XF86XK_LaunchA 0x1008FF4A -#define XF86XK_LaunchB 0x1008FF4B -#define XF86XK_LaunchC 0x1008FF4C -#define XF86XK_LaunchD 0x1008FF4D -#define XF86XK_LaunchE 0x1008FF4E -#define XF86XK_LaunchF 0x1008FF4F +#define XF86XK_MonBrightnessUp 0x1008FF02 +#define XF86XK_MonBrightnessDown 0x1008FF03 +#define XF86XK_KbdLightOnOff 0x1008FF04 +#define XF86XK_KbdBrightnessUp 0x1008FF05 +#define XF86XK_KbdBrightnessDown 0x1008FF06 +#define XF86XK_Standby 0x1008FF10 +#define XF86XK_AudioLowerVolume 0x1008FF11 +#define XF86XK_AudioMute 0x1008FF12 +#define XF86XK_AudioRaiseVolume 0x1008FF13 +#define XF86XK_AudioPlay 0x1008FF14 +#define XF86XK_AudioStop 0x1008FF15 +#define XF86XK_AudioPrev 0x1008FF16 +#define XF86XK_AudioNext 0x1008FF17 +#define XF86XK_HomePage 0x1008FF18 +#define XF86XK_Mail 0x1008FF19 +#define XF86XK_Start 0x1008FF1A +#define XF86XK_Search 0x1008FF1B +#define XF86XK_AudioRecord 0x1008FF1C +#define XF86XK_Calculator 0x1008FF1D +#define XF86XK_Memo 0x1008FF1E +#define XF86XK_ToDoList 0x1008FF1F +#define XF86XK_Calendar 0x1008FF20 +#define XF86XK_PowerDown 0x1008FF21 +#define XF86XK_ContrastAdjust 0x1008FF22 +#define XF86XK_Back 0x1008FF26 +#define XF86XK_Forward 0x1008FF27 +#define XF86XK_Stop 0x1008FF28 +#define XF86XK_Refresh 0x1008FF29 +#define XF86XK_PowerOff 0x1008FF2A +#define XF86XK_WakeUp 0x1008FF2B +#define XF86XK_Eject 0x1008FF2C +#define XF86XK_ScreenSaver 0x1008FF2D +#define XF86XK_WWW 0x1008FF2E +#define XF86XK_Sleep 0x1008FF2F +#define XF86XK_Favorites 0x1008FF30 +#define XF86XK_AudioPause 0x1008FF31 +#define XF86XK_AudioMedia 0x1008FF32 +#define XF86XK_MyComputer 0x1008FF33 +#define XF86XK_LightBulb 0x1008FF35 +#define XF86XK_Shop 0x1008FF36 +#define XF86XK_History 0x1008FF37 +#define XF86XK_OpenURL 0x1008FF38 +#define XF86XK_AddFavorite 0x1008FF39 +#define XF86XK_HotLinks 0x1008FF3A +#define XF86XK_BrightnessAdjust 0x1008FF3B +#define XF86XK_Finance 0x1008FF3C +#define XF86XK_Community 0x1008FF3D +#define XF86XK_AudioRewind 0x1008FF3E +#define XF86XK_BackForward 0x1008FF3F +#define XF86XK_Launch0 0x1008FF40 +#define XF86XK_Launch1 0x1008FF41 +#define XF86XK_Launch2 0x1008FF42 +#define XF86XK_Launch3 0x1008FF43 +#define XF86XK_Launch4 0x1008FF44 +#define XF86XK_Launch5 0x1008FF45 +#define XF86XK_Launch6 0x1008FF46 +#define XF86XK_Launch7 0x1008FF47 +#define XF86XK_Launch8 0x1008FF48 +#define XF86XK_Launch9 0x1008FF49 +#define XF86XK_LaunchA 0x1008FF4A +#define XF86XK_LaunchB 0x1008FF4B +#define XF86XK_LaunchC 0x1008FF4C +#define XF86XK_LaunchD 0x1008FF4D +#define XF86XK_LaunchE 0x1008FF4E +#define XF86XK_LaunchF 0x1008FF4F +#define XF86XK_ApplicationLeft 0x1008FF50 +#define XF86XK_ApplicationRight 0x1008FF51 +#define XF86XK_Book 0x1008FF52 +#define XF86XK_CD 0x1008FF53 +#define XF86XK_Calculater 0x1008FF54 +#define XF86XK_Clear 0x1008FF55 +#define XF86XK_ClearGrab 0x1008FE21 +#define XF86XK_Close 0x1008FF56 +#define XF86XK_Copy 0x1008FF57 +#define XF86XK_Cut 0x1008FF58 +#define XF86XK_Display 0x1008FF59 +#define XF86XK_DOS 0x1008FF5A +#define XF86XK_Documents 0x1008FF5B +#define XF86XK_Excel 0x1008FF5C +#define XF86XK_Explorer 0x1008FF5D +#define XF86XK_Game 0x1008FF5E +#define XF86XK_Go 0x1008FF5F +#define XF86XK_iTouch 0x1008FF60 +#define XF86XK_LogOff 0x1008FF61 +#define XF86XK_Market 0x1008FF62 +#define XF86XK_Meeting 0x1008FF63 +#define XF86XK_MenuKB 0x1008FF65 +#define XF86XK_MenuPB 0x1008FF66 +#define XF86XK_MySites 0x1008FF67 +#define XF86XK_News 0x1008FF69 +#define XF86XK_OfficeHome 0x1008FF6A +#define XF86XK_Option 0x1008FF6C +#define XF86XK_Paste 0x1008FF6D +#define XF86XK_Phone 0x1008FF6E +#define XF86XK_Reply 0x1008FF72 +#define XF86XK_Reload 0x1008FF73 +#define XF86XK_RotateWindows 0x1008FF74 +#define XF86XK_RotationPB 0x1008FF75 +#define XF86XK_RotationKB 0x1008FF76 +#define XF86XK_Save 0x1008FF77 +#define XF86XK_Send 0x1008FF7B +#define XF86XK_Spell 0x1008FF7C +#define XF86XK_SplitScreen 0x1008FF7D +#define XF86XK_Support 0x1008FF7E +#define XF86XK_TaskPane 0x1008FF7F +#define XF86XK_Terminal 0x1008FF80 +#define XF86XK_Tools 0x1008FF81 +#define XF86XK_Travel 0x1008FF82 +#define XF86XK_Video 0x1008FF87 +#define XF86XK_Word 0x1008FF89 +#define XF86XK_Xfer 0x1008FF8A +#define XF86XK_ZoomIn 0x1008FF8B +#define XF86XK_ZoomOut 0x1008FF8C +#define XF86XK_Away 0x1008FF8D +#define XF86XK_Messenger 0x1008FF8E +#define XF86XK_WebCam 0x1008FF8F +#define XF86XK_MailForward 0x1008FF90 +#define XF86XK_Pictures 0x1008FF91 +#define XF86XK_Music 0x1008FF92 +#define XF86XK_Battery 0x1008FF93 +#define XF86XK_Bluetooth 0x1008FF94 +#define XF86XK_WLAN 0x1008FF95 +#define XF86XK_UWB 0x1008FF96 +#define XF86XK_AudioForward 0x1008FF97 +#define XF86XK_AudioRepeat 0x1008FF98 +#define XF86XK_AudioRandomPlay 0x1008FF99 +#define XF86XK_Subtitle 0x1008FF9A +#define XF86XK_AudioCycleTrack 0x1008FF9B +#define XF86XK_Time 0x1008FF9F +#define XF86XK_Select 0x1008FFA0 +#define XF86XK_View 0x1008FFA1 +#define XF86XK_TopMenu 0x1008FFA2 +#define XF86XK_Suspend 0x1008FFA7 +#define XF86XK_Hibernate 0x1008FFA8 + + // end of XF86keysyms.h // Special keys used by Qtopia, mapped into the X11 private keypad range. @@ -942,10 +1039,8 @@ static const unsigned int KeyTbl[] = { XK_dead_hook, Qt::Key_Dead_Hook, XK_dead_horn, Qt::Key_Dead_Horn, - // Special multimedia keys - // currently only tested with MS internet keyboard - - // browsing keys + // Special keys from X.org - This include multimedia keys, + // wireless/bluetooth/uwb keys, special launcher keys, etc. XF86XK_Back, Qt::Key_Back, XF86XK_Forward, Qt::Key_Forward, XF86XK_Stop, Qt::Key_Stop, @@ -955,8 +1050,6 @@ static const unsigned int KeyTbl[] = { XF86XK_OpenURL, Qt::Key_OpenUrl, XF86XK_HomePage, Qt::Key_HomePage, XF86XK_Search, Qt::Key_Search, - - // media keys XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, XF86XK_AudioMute, Qt::Key_VolumeMute, XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, @@ -965,13 +1058,106 @@ static const unsigned int KeyTbl[] = { XF86XK_AudioPrev, Qt::Key_MediaPrevious, XF86XK_AudioNext, Qt::Key_MediaNext, XF86XK_AudioRecord, Qt::Key_MediaRecord, - - // launch keys XF86XK_Mail, Qt::Key_LaunchMail, XF86XK_MyComputer, Qt::Key_Launch0, - XF86XK_Calculator, Qt::Key_Launch1, + XF86XK_Calculator, Qt::Key_Calculator, + XF86XK_Memo, Qt::Key_Memo, + XF86XK_ToDoList, Qt::Key_ToDoList, + XF86XK_Calendar, Qt::Key_Calendar, + XF86XK_PowerDown, Qt::Key_PowerDown, + XF86XK_ContrastAdjust, Qt::Key_ContrastAdjust, XF86XK_Standby, Qt::Key_Standby, - + XF86XK_MonBrightnessUp, Qt::Key_MonBrightnessUp, + XF86XK_MonBrightnessDown, Qt::Key_MonBrightnessDown, + XF86XK_KbdLightOnOff, Qt::Key_KeyboardLightOnOff, + XF86XK_KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp, + XF86XK_KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown, + XF86XK_PowerOff, Qt::Key_PowerOff, + XF86XK_WakeUp, Qt::Key_WakeUp, + XF86XK_Eject, Qt::Key_Eject, + XF86XK_ScreenSaver, Qt::Key_ScreenSaver, + XF86XK_WWW, Qt::Key_WWW, + XF86XK_Sleep, Qt::Key_Sleep, + XF86XK_LightBulb, Qt::Key_LightBulb, + XF86XK_Shop, Qt::Key_Shop, + XF86XK_History, Qt::Key_History, + XF86XK_AddFavorite, Qt::Key_AddFavorite, + XF86XK_HotLinks, Qt::Key_HotLinks, + XF86XK_BrightnessAdjust, Qt::Key_BrightnessAdjust, + XF86XK_Finance, Qt::Key_Finance, + XF86XK_Community, Qt::Key_Community, + XF86XK_AudioRewind, Qt::Key_AudioRewind, + XF86XK_BackForward, Qt::Key_BackForward, + XF86XK_ApplicationLeft, Qt::Key_ApplicationLeft, + XF86XK_ApplicationRight, Qt::Key_ApplicationRight, + XF86XK_Book, Qt::Key_Book, + XF86XK_CD, Qt::Key_CD, + XF86XK_Calculater, Qt::Key_Calculator, + XF86XK_Clear, Qt::Key_Clear, + XF86XK_ClearGrab, Qt::Key_ClearGrab, + XF86XK_Close, Qt::Key_Close, + XF86XK_Copy, Qt::Key_Copy, + XF86XK_Cut, Qt::Key_Cut, + XF86XK_Display, Qt::Key_Display, + XF86XK_DOS, Qt::Key_DOS, + XF86XK_Documents, Qt::Key_Documents, + XF86XK_Excel, Qt::Key_Excel, + XF86XK_Explorer, Qt::Key_Explorer, + XF86XK_Game, Qt::Key_Game, + XF86XK_Go, Qt::Key_Go, + XF86XK_iTouch, Qt::Key_iTouch, + XF86XK_LogOff, Qt::Key_LogOff, + XF86XK_Market, Qt::Key_Market, + XF86XK_Meeting, Qt::Key_Meeting, + XF86XK_MenuKB, Qt::Key_MenuKB, + XF86XK_MenuPB, Qt::Key_MenuPB, + XF86XK_MySites, Qt::Key_MySites, + XF86XK_News, Qt::Key_News, + XF86XK_OfficeHome, Qt::Key_OfficeHome, + XF86XK_Option, Qt::Key_Option, + XF86XK_Paste, Qt::Key_Paste, + XF86XK_Phone, Qt::Key_Phone, + XF86XK_Reply, Qt::Key_Reply, + XF86XK_Reload, Qt::Key_Reload, + XF86XK_RotateWindows, Qt::Key_RotateWindows, + XF86XK_RotationPB, Qt::Key_RotationPB, + XF86XK_RotationKB, Qt::Key_RotationKB, + XF86XK_Save, Qt::Key_Save, + XF86XK_Send, Qt::Key_Send, + XF86XK_Spell, Qt::Key_Spell, + XF86XK_SplitScreen, Qt::Key_SplitScreen, + XF86XK_Support, Qt::Key_Support, + XF86XK_TaskPane, Qt::Key_TaskPane, + XF86XK_Terminal, Qt::Key_Terminal, + XF86XK_Tools, Qt::Key_Tools, + XF86XK_Travel, Qt::Key_Travel, + XF86XK_Video, Qt::Key_Video, + XF86XK_Word, Qt::Key_Word, + XF86XK_Xfer, Qt::Key_Xfer, + XF86XK_ZoomIn, Qt::Key_ZoomIn, + XF86XK_ZoomOut, Qt::Key_ZoomOut, + XF86XK_Away, Qt::Key_Away, + XF86XK_Messenger, Qt::Key_Messenger, + XF86XK_WebCam, Qt::Key_WebCam, + XF86XK_MailForward, Qt::Key_MailForward, + XF86XK_Pictures, Qt::Key_Pictures, + XF86XK_Music, Qt::Key_Music, + XF86XK_Battery, Qt::Key_Battery, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_WLAN, Qt::Key_WLAN, + XF86XK_UWB, Qt::Key_UWB, + XF86XK_AudioForward, Qt::Key_AudioForward, + XF86XK_AudioRepeat, Qt::Key_AudioRepeat, + XF86XK_AudioRandomPlay, Qt::Key_AudioRandomPlay, + XF86XK_Subtitle, Qt::Key_Subtitle, + XF86XK_AudioCycleTrack, Qt::Key_AudioCycleTrack, + XF86XK_Time, Qt::Key_Time, + XF86XK_Select, Qt::Key_Select, + XF86XK_View, Qt::Key_View, + XF86XK_TopMenu, Qt::Key_TopMenu, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_Suspend, Qt::Key_Suspend, + XF86XK_Hibernate, Qt::Key_Hibernate, XF86XK_Launch0, Qt::Key_Launch2, XF86XK_Launch1, Qt::Key_Launch3, XF86XK_Launch2, Qt::Key_Launch4, diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index b44ef7f..1a76083 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -416,47 +416,139 @@ static const struct { { Qt::Key_Menu, QT_TRANSLATE_NOOP("QShortcut", "Menu") }, { Qt::Key_Help, QT_TRANSLATE_NOOP("QShortcut", "Help") }, - // Multimedia keys - { Qt::Key_Back, QT_TRANSLATE_NOOP("QShortcut", "Back") }, - { Qt::Key_Forward, QT_TRANSLATE_NOOP("QShortcut", "Forward") }, - { Qt::Key_Stop, QT_TRANSLATE_NOOP("QShortcut", "Stop") }, - { Qt::Key_Refresh, QT_TRANSLATE_NOOP("QShortcut", "Refresh") }, - { Qt::Key_VolumeDown, QT_TRANSLATE_NOOP("QShortcut", "Volume Down") }, - { Qt::Key_VolumeMute, QT_TRANSLATE_NOOP("QShortcut", "Volume Mute") }, - { Qt::Key_VolumeUp, QT_TRANSLATE_NOOP("QShortcut", "Volume Up") }, - { Qt::Key_BassBoost, QT_TRANSLATE_NOOP("QShortcut", "Bass Boost") }, - { Qt::Key_BassUp, QT_TRANSLATE_NOOP("QShortcut", "Bass Up") }, - { Qt::Key_BassDown, QT_TRANSLATE_NOOP("QShortcut", "Bass Down") }, - { Qt::Key_TrebleUp, QT_TRANSLATE_NOOP("QShortcut", "Treble Up") }, - { Qt::Key_TrebleDown, QT_TRANSLATE_NOOP("QShortcut", "Treble Down") }, - { Qt::Key_MediaPlay, QT_TRANSLATE_NOOP("QShortcut", "Media Play") }, - { Qt::Key_MediaStop, QT_TRANSLATE_NOOP("QShortcut", "Media Stop") }, - { Qt::Key_MediaPrevious,QT_TRANSLATE_NOOP("QShortcut", "Media Previous") }, - { Qt::Key_MediaNext, QT_TRANSLATE_NOOP("QShortcut", "Media Next") }, - { Qt::Key_MediaRecord, QT_TRANSLATE_NOOP("QShortcut", "Media Record") }, - { Qt::Key_HomePage, QT_TRANSLATE_NOOP("QShortcut", "Home Page") }, - { Qt::Key_Favorites, QT_TRANSLATE_NOOP("QShortcut", "Favorites") }, - { Qt::Key_Search, QT_TRANSLATE_NOOP("QShortcut", "Search") }, - { Qt::Key_Standby, QT_TRANSLATE_NOOP("QShortcut", "Standby") }, - { Qt::Key_OpenUrl, QT_TRANSLATE_NOOP("QShortcut", "Open URL") }, - { Qt::Key_LaunchMail, QT_TRANSLATE_NOOP("QShortcut", "Launch Mail") }, - { Qt::Key_LaunchMedia, QT_TRANSLATE_NOOP("QShortcut", "Launch Media") }, - { Qt::Key_Launch0, QT_TRANSLATE_NOOP("QShortcut", "Launch (0)") }, - { Qt::Key_Launch1, QT_TRANSLATE_NOOP("QShortcut", "Launch (1)") }, - { Qt::Key_Launch2, QT_TRANSLATE_NOOP("QShortcut", "Launch (2)") }, - { Qt::Key_Launch3, QT_TRANSLATE_NOOP("QShortcut", "Launch (3)") }, - { Qt::Key_Launch4, QT_TRANSLATE_NOOP("QShortcut", "Launch (4)") }, - { Qt::Key_Launch5, QT_TRANSLATE_NOOP("QShortcut", "Launch (5)") }, - { Qt::Key_Launch6, QT_TRANSLATE_NOOP("QShortcut", "Launch (6)") }, - { Qt::Key_Launch7, QT_TRANSLATE_NOOP("QShortcut", "Launch (7)") }, - { Qt::Key_Launch8, QT_TRANSLATE_NOOP("QShortcut", "Launch (8)") }, - { Qt::Key_Launch9, QT_TRANSLATE_NOOP("QShortcut", "Launch (9)") }, - { Qt::Key_LaunchA, QT_TRANSLATE_NOOP("QShortcut", "Launch (A)") }, - { Qt::Key_LaunchB, QT_TRANSLATE_NOOP("QShortcut", "Launch (B)") }, - { Qt::Key_LaunchC, QT_TRANSLATE_NOOP("QShortcut", "Launch (C)") }, - { Qt::Key_LaunchD, QT_TRANSLATE_NOOP("QShortcut", "Launch (D)") }, - { Qt::Key_LaunchE, QT_TRANSLATE_NOOP("QShortcut", "Launch (E)") }, - { Qt::Key_LaunchF, QT_TRANSLATE_NOOP("QShortcut", "Launch (F)") }, + // Special keys + // Includes multimedia, launcher, lan keys ( bluetooth, wireless ) + // window navigation + { Qt::Key_Back, QT_TRANSLATE_NOOP("QShortcut", "Back") }, + { Qt::Key_Forward, QT_TRANSLATE_NOOP("QShortcut", "Forward") }, + { Qt::Key_Stop, QT_TRANSLATE_NOOP("QShortcut", "Stop") }, + { Qt::Key_Refresh, QT_TRANSLATE_NOOP("QShortcut", "Refresh") }, + { Qt::Key_VolumeDown, QT_TRANSLATE_NOOP("QShortcut", "Volume Down") }, + { Qt::Key_VolumeMute, QT_TRANSLATE_NOOP("QShortcut", "Volume Mute") }, + { Qt::Key_VolumeUp, QT_TRANSLATE_NOOP("QShortcut", "Volume Up") }, + { Qt::Key_BassBoost, QT_TRANSLATE_NOOP("QShortcut", "Bass Boost") }, + { Qt::Key_BassUp, QT_TRANSLATE_NOOP("QShortcut", "Bass Up") }, + { Qt::Key_BassDown, QT_TRANSLATE_NOOP("QShortcut", "Bass Down") }, + { Qt::Key_TrebleUp, QT_TRANSLATE_NOOP("QShortcut", "Treble Up") }, + { Qt::Key_TrebleDown, QT_TRANSLATE_NOOP("QShortcut", "Treble Down") }, + { Qt::Key_MediaPlay, QT_TRANSLATE_NOOP("QShortcut", "Media Play") }, + { Qt::Key_MediaStop, QT_TRANSLATE_NOOP("QShortcut", "Media Stop") }, + { Qt::Key_MediaPrevious, QT_TRANSLATE_NOOP("QShortcut", "Media Previous") }, + { Qt::Key_MediaNext, QT_TRANSLATE_NOOP("QShortcut", "Media Next") }, + { Qt::Key_MediaRecord, QT_TRANSLATE_NOOP("QShortcut", "Media Record") }, + { Qt::Key_HomePage, QT_TRANSLATE_NOOP("QShortcut", "Home Page") }, + { Qt::Key_Favorites, QT_TRANSLATE_NOOP("QShortcut", "Favorites") }, + { Qt::Key_Search, QT_TRANSLATE_NOOP("QShortcut", "Search") }, + { Qt::Key_Standby, QT_TRANSLATE_NOOP("QShortcut", "Standby") }, + { Qt::Key_OpenUrl, QT_TRANSLATE_NOOP("QShortcut", "Open URL") }, + { Qt::Key_LaunchMail, QT_TRANSLATE_NOOP("QShortcut", "Launch Mail") }, + { Qt::Key_LaunchMedia, QT_TRANSLATE_NOOP("QShortcut", "Launch Media") }, + { Qt::Key_Launch0, QT_TRANSLATE_NOOP("QShortcut", "Launch (0)") }, + { Qt::Key_Launch1, QT_TRANSLATE_NOOP("QShortcut", "Launch (1)") }, + { Qt::Key_Launch2, QT_TRANSLATE_NOOP("QShortcut", "Launch (2)") }, + { Qt::Key_Launch3, QT_TRANSLATE_NOOP("QShortcut", "Launch (3)") }, + { Qt::Key_Launch4, QT_TRANSLATE_NOOP("QShortcut", "Launch (4)") }, + { Qt::Key_Launch5, QT_TRANSLATE_NOOP("QShortcut", "Launch (5)") }, + { Qt::Key_Launch6, QT_TRANSLATE_NOOP("QShortcut", "Launch (6)") }, + { Qt::Key_Launch7, QT_TRANSLATE_NOOP("QShortcut", "Launch (7)") }, + { Qt::Key_Launch8, QT_TRANSLATE_NOOP("QShortcut", "Launch (8)") }, + { Qt::Key_Launch9, QT_TRANSLATE_NOOP("QShortcut", "Launch (9)") }, + { Qt::Key_LaunchA, QT_TRANSLATE_NOOP("QShortcut", "Launch (A)") }, + { Qt::Key_LaunchB, QT_TRANSLATE_NOOP("QShortcut", "Launch (B)") }, + { Qt::Key_LaunchC, QT_TRANSLATE_NOOP("QShortcut", "Launch (C)") }, + { Qt::Key_LaunchD, QT_TRANSLATE_NOOP("QShortcut", "Launch (D)") }, + { Qt::Key_LaunchE, QT_TRANSLATE_NOOP("QShortcut", "Launch (E)") }, + { Qt::Key_LaunchF, QT_TRANSLATE_NOOP("QShortcut", "Launch (F)") }, + { Qt::Key_MonBrightnessUp, QT_TRANSLATE_NOOP("QShortcut", "Monitor Brightness Up") }, + { Qt::Key_MonBrightnessDown, QT_TRANSLATE_NOOP("QShortcut", "Monitor Brightness Down") }, + { Qt::Key_KeyboardLightOnOff, QT_TRANSLATE_NOOP("QShortcut", "Keyboard Light On/Off") }, + { Qt::Key_KeyboardBrightnessUp, QT_TRANSLATE_NOOP("QShortcut", "Keyboard Brightness Up") }, + { Qt::Key_KeyboardBrightnessDown, QT_TRANSLATE_NOOP("QShortcut", "Keyboard Brightness Down") }, + { Qt::Key_PowerOff, QT_TRANSLATE_NOOP("QShortcut", "Power Off") }, + { Qt::Key_WakeUp, QT_TRANSLATE_NOOP("QShortcut", "Wake Up") }, + { Qt::Key_Eject, QT_TRANSLATE_NOOP("QShortcut", "Eject") }, + { Qt::Key_ScreenSaver, QT_TRANSLATE_NOOP("QShortcut", "Screensaver") }, + { Qt::Key_WWW, QT_TRANSLATE_NOOP("QShortcut", "WWW") }, + { Qt::Key_Sleep, QT_TRANSLATE_NOOP("QShortcut", "Sleep") }, + { Qt::Key_LightBulb, QT_TRANSLATE_NOOP("QShortcut", "LightBulb") }, + { Qt::Key_Shop, QT_TRANSLATE_NOOP("QShortcut", "Shop") }, + { Qt::Key_History, QT_TRANSLATE_NOOP("QShortcut", "History") }, + { Qt::Key_AddFavorite, QT_TRANSLATE_NOOP("QShortcut", "Add Favorite") }, + { Qt::Key_HotLinks, QT_TRANSLATE_NOOP("QShortcut", "Hot Links") }, + { Qt::Key_BrightnessAdjust, QT_TRANSLATE_NOOP("QShortcut", "Adjust Brightness") }, + { Qt::Key_Finance, QT_TRANSLATE_NOOP("QShortcut", "Finance") }, + { Qt::Key_Community, QT_TRANSLATE_NOOP("QShortcut", "Community") }, + { Qt::Key_AudioRewind, QT_TRANSLATE_NOOP("QShortcut", "Audio Rewind") }, + { Qt::Key_BackForward, QT_TRANSLATE_NOOP("QShortcut", "Back Forward") }, + { Qt::Key_ApplicationLeft, QT_TRANSLATE_NOOP("QShortcut", "Application Left") }, + { Qt::Key_ApplicationRight, QT_TRANSLATE_NOOP("QShortcut", "Application Right") }, + { Qt::Key_Book, QT_TRANSLATE_NOOP("QShortcut", "Book") }, + { Qt::Key_CD, QT_TRANSLATE_NOOP("QShortcut", "CD") }, + { Qt::Key_Calculator, QT_TRANSLATE_NOOP("QShortcut", "Calculator") }, + { Qt::Key_Clear, QT_TRANSLATE_NOOP("QShortcut", "Clear") }, + { Qt::Key_ClearGrab, QT_TRANSLATE_NOOP("QShortcut", "Clear Grab") }, + { Qt::Key_Close, QT_TRANSLATE_NOOP("QShortcut", "Close") }, + { Qt::Key_Copy, QT_TRANSLATE_NOOP("QShortcut", "Copy") }, + { Qt::Key_Cut, QT_TRANSLATE_NOOP("QShortcut", "Cut") }, + { Qt::Key_Display, QT_TRANSLATE_NOOP("QShortcut", "Display") }, + { Qt::Key_DOS, QT_TRANSLATE_NOOP("QShortcut", "DOS") }, + { Qt::Key_Documents, QT_TRANSLATE_NOOP("QShortcut", "Documents") }, + { Qt::Key_Excel, QT_TRANSLATE_NOOP("QShortcut", "Spreadsheet") }, + { Qt::Key_Explorer, QT_TRANSLATE_NOOP("QShortcut", "Browser") }, + { Qt::Key_Game, QT_TRANSLATE_NOOP("QShortcut", "Game") }, + { Qt::Key_Go, QT_TRANSLATE_NOOP("QShortcut", "Go") }, + { Qt::Key_iTouch, QT_TRANSLATE_NOOP("QShortcut", "iTouch") }, + { Qt::Key_LogOff, QT_TRANSLATE_NOOP("QShortcut", "Logoff") }, + { Qt::Key_Market, QT_TRANSLATE_NOOP("QShortcut", "Market") }, + { Qt::Key_Meeting, QT_TRANSLATE_NOOP("QShortcut", "Meeting") }, + { Qt::Key_MenuKB, QT_TRANSLATE_NOOP("QShortcut", "Keyboard Menu") }, + { Qt::Key_MenuPB, QT_TRANSLATE_NOOP("QShortcut", "Menu PB") }, + { Qt::Key_MySites, QT_TRANSLATE_NOOP("QShortcut", "My Sites") }, + { Qt::Key_News, QT_TRANSLATE_NOOP("QShortcut", "News") }, + { Qt::Key_OfficeHome, QT_TRANSLATE_NOOP("QShortcut", "Home Office") }, + { Qt::Key_Option, QT_TRANSLATE_NOOP("QShortcut", "Option") }, + { Qt::Key_Paste, QT_TRANSLATE_NOOP("QShortcut", "Paste") }, + { Qt::Key_Phone, QT_TRANSLATE_NOOP("QShortcut", "Phone") }, + { Qt::Key_Reply, QT_TRANSLATE_NOOP("QShortcut", "Reply") }, + { Qt::Key_Reload, QT_TRANSLATE_NOOP("QShortcut", "Reload") }, + { Qt::Key_RotateWindows, QT_TRANSLATE_NOOP("QShortcut", "Rotate Windows") }, + { Qt::Key_RotationPB, QT_TRANSLATE_NOOP("QShortcut", "Rotation PB") }, + { Qt::Key_RotationKB, QT_TRANSLATE_NOOP("QShortcut", "Rotation KB") }, + { Qt::Key_Save, QT_TRANSLATE_NOOP("QShortcut", "Save") }, + { Qt::Key_Send, QT_TRANSLATE_NOOP("QShortcut", "Send") }, + { Qt::Key_Spell, QT_TRANSLATE_NOOP("QShortcut", "Spellchecker") }, + { Qt::Key_SplitScreen, QT_TRANSLATE_NOOP("QShortcut", "Split Screen") }, + { Qt::Key_Support, QT_TRANSLATE_NOOP("QShortcut", "Support") }, + { Qt::Key_TaskPane, QT_TRANSLATE_NOOP("QShortcut", "Task Panel") }, + { Qt::Key_Terminal, QT_TRANSLATE_NOOP("QShortcut", "Terminal") }, + { Qt::Key_Tools, QT_TRANSLATE_NOOP("QShortcut", "Tools") }, + { Qt::Key_Travel, QT_TRANSLATE_NOOP("QShortcut", "Travel") }, + { Qt::Key_Video, QT_TRANSLATE_NOOP("QShortcut", "Video") }, + { Qt::Key_Word, QT_TRANSLATE_NOOP("QShortcut", "Word Processor") }, + { Qt::Key_Xfer, QT_TRANSLATE_NOOP("QShortcut", "XFer") }, + { Qt::Key_ZoomIn, QT_TRANSLATE_NOOP("QShortcut", "Zoom In") }, + { Qt::Key_ZoomOut, QT_TRANSLATE_NOOP("QShortcut", "Zoom Out") }, + { Qt::Key_Away, QT_TRANSLATE_NOOP("QShortcut", "Away") }, + { Qt::Key_Messenger, QT_TRANSLATE_NOOP("QShortcut", "Messenger") }, + { Qt::Key_WebCam, QT_TRANSLATE_NOOP("QShortcut", "WebCam") }, + { Qt::Key_MailForward, QT_TRANSLATE_NOOP("QShortcut", "Mail Forward") }, + { Qt::Key_Pictures, QT_TRANSLATE_NOOP("QShortcut", "Pictures") }, + { Qt::Key_Music, QT_TRANSLATE_NOOP("QShortcut", "Music") }, + { Qt::Key_Battery, QT_TRANSLATE_NOOP("QShortcut", "Battery") }, + { Qt::Key_Bluetooth, QT_TRANSLATE_NOOP("QShortcut", "Bluetooth") }, + { Qt::Key_WLAN, QT_TRANSLATE_NOOP("QShortcut", "Wireless") }, + { Qt::Key_UWB, QT_TRANSLATE_NOOP("QShortcut", "Ultra Wide Band") }, + { Qt::Key_AudioForward, QT_TRANSLATE_NOOP("QShortcut", "Audio Forward") }, + { Qt::Key_AudioRepeat, QT_TRANSLATE_NOOP("QShortcut", "Audio Repeat") }, + { Qt::Key_AudioRandomPlay, QT_TRANSLATE_NOOP("QShortcut", "Audio Random Play") }, + { Qt::Key_Subtitle, QT_TRANSLATE_NOOP("QShortcut", "Subtitle") }, + { Qt::Key_AudioCycleTrack, QT_TRANSLATE_NOOP("QShortcut", "Audio Cycle Track") }, + { Qt::Key_Time, QT_TRANSLATE_NOOP("QShortcut", "Time") }, + { Qt::Key_Select, QT_TRANSLATE_NOOP("QShortcut", "Select") }, + { Qt::Key_View, QT_TRANSLATE_NOOP("QShortcut", "View") }, + { Qt::Key_TopMenu, QT_TRANSLATE_NOOP("QShortcut", "Top Menu") }, + { Qt::Key_Suspend, QT_TRANSLATE_NOOP("QShortcut", "Suspend") }, + { Qt::Key_Hibernate, QT_TRANSLATE_NOOP("QShortcut", "Hibernate") }, // -------------------------------------------------------------- // More consistent namings diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm index 7b19a54..7019580 100644 --- a/src/gui/kernel/qmacgesturerecognizer_mac.mm +++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm @@ -218,7 +218,7 @@ QMacPanGestureRecognizer::filterEvent(QGesture *gesture, QObject *target, QEvent const QPointF p = QCursor::pos(); const QPointF posOffset = p - _lastPos; g->setLastOffset(g->offset()); - g->setOffset(QSizeF(posOffset.x(), posOffset.y())); + g->setOffset(QPointF(posOffset.x(), posOffset.y())); g->setTotalOffset(g->lastOffset() + g->offset()); _lastPos = p; return QGestureRecognizer::GestureTriggered; @@ -256,9 +256,9 @@ void QMacPanGestureRecognizer::reset(QGesture *gesture) _startPos = QPointF(); _lastPos = QPointF(); _panCanceled = true; - g->setOffset(QSizeF(0, 0)); - g->setLastOffset(QSizeF(0, 0)); - g->setTotalOffset(QSizeF(0, 0)); + g->setOffset(QPointF(0, 0)); + g->setLastOffset(QPointF(0, 0)); + g->setTotalOffset(QPointF(0, 0)); g->setAcceleration(qreal(1)); QGestureRecognizer::reset(gesture); } diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 6116a5e..21795b4 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -48,6 +48,7 @@ #include "private/qsoftkeymanager_p.h" #include "private/qobject_p.h" +#ifndef QT_NO_SOFTKEYMANAGER QT_BEGIN_NAMESPACE #ifdef Q_WS_S60 @@ -139,11 +140,18 @@ QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key QScopedPointer<QAction> action(createAction(standardKey, actionWidget)); connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent())); - + connect(action.data(), SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*))); QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key); return action.take(); } +void QSoftKeyManager::cleanupHash(QObject* obj) +{ + Q_D(QSoftKeyManager); + QAction *action = qobject_cast<QAction*>(obj); + d->keyedActions.remove(action); +} + void QSoftKeyManager::sendKeyEvent() { Q_D(QSoftKeyManager); @@ -189,7 +197,8 @@ bool QSoftKeyManager::event(QEvent *e) } while (source); QSoftKeyManagerPrivate::softKeySource = source; - QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys); + if (source) + QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys); return true; } return false; @@ -199,6 +208,7 @@ bool QSoftKeyManager::event(QEvent *e) void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) { CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); + nativeContainer->DrawableWindow()->SetOrdinalPosition(0); nativeContainer->DrawableWindow()->SetPointerCapturePriority(1); //keep softkeys available in modal dialog QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS)); @@ -237,7 +247,8 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) } } - if (needsExitButton) + Qt::WindowType sourceWindowType = QSoftKeyManagerPrivate::softKeySource->window()->windowType(); + if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup) QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation @@ -275,4 +286,4 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &) #endif QT_END_NAMESPACE - +#endif //QT_NO_SOFTKEYMANAGER diff --git a/src/gui/kernel/qsoftkeymanager_p.h b/src/gui/kernel/qsoftkeymanager_p.h index b455445..796e080 100644 --- a/src/gui/kernel/qsoftkeymanager_p.h +++ b/src/gui/kernel/qsoftkeymanager_p.h @@ -58,6 +58,7 @@ QT_BEGIN_HEADER +#ifndef QT_NO_SOFTKEYMANAGER QT_BEGIN_NAMESPACE class QSoftKeyManagerPrivate; @@ -96,10 +97,12 @@ protected: Q_DISABLE_COPY(QSoftKeyManager) private Q_SLOTS: + void cleanupHash(QObject* obj); void sendKeyEvent(); }; QT_END_NAMESPACE +#endif //QT_NO_SOFTKEYMANAGER QT_END_HEADER diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index dfc3499..dec2311 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -73,7 +73,7 @@ QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, Q result = QGestureRecognizer::MaybeGesture; QTouchEvent::TouchPoint p = ev->touchPoints().at(0); d->lastPosition = p.pos().toPoint(); - d->lastOffset = d->totalOffset = d->offset = QSize(); + d->lastOffset = d->totalOffset = d->offset = QPointF(); break; } case QEvent::TouchEnd: { @@ -83,7 +83,7 @@ QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, Q QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); d->lastOffset = d->offset; d->offset = - QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + QPointF(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; d->totalOffset += d->offset; } @@ -99,11 +99,11 @@ QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, Q QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); d->lastOffset = d->offset; d->offset = - QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + QPointF(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; d->totalOffset += d->offset; - if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || - d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { + if (d->totalOffset.x() > 10 || d->totalOffset.y() > 10 || + d->totalOffset.x() < -10 || d->totalOffset.y() < -10) { result = QGestureRecognizer::GestureTriggered; } else { result = QGestureRecognizer::MaybeGesture; @@ -128,7 +128,7 @@ void QPanGestureRecognizer::reset(QGesture *state) QPanGesture *pan = static_cast<QPanGesture*>(state); QPanGesturePrivate *d = pan->d_func(); - d->totalOffset = d->lastOffset = d->offset = QSizeF(); + d->totalOffset = d->lastOffset = d->offset = QPointF(); d->lastPosition = QPoint(); d->acceleration = 0; @@ -140,7 +140,6 @@ void QPanGestureRecognizer::reset(QGesture *state) QGestureRecognizer::reset(state); } -/*! \internal */ /* bool QPanGestureRecognizer::event(QEvent *event) { diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 2b2259c..c0fb8aa 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1152,16 +1152,23 @@ CGFloat qt_mac_get_scalefactor() #endif } -QString qt_mac_get_pasteboardString() +QString qt_mac_get_pasteboardString(OSPasteboardRef paste) { QMacCocoaAutoReleasePool pool; - NSPasteboard *pb = [NSPasteboard generalPasteboard]; - NSString *text = [pb stringForType:NSStringPboardType]; - if (text) { - return qt_mac_NSStringToQString(text); + NSPasteboard *pb = nil; + CFStringRef pbname; + if (PasteboardCopyName (paste, &pbname)) { + pb = [NSPasteboard generalPasteboard]; } else { - return QString(); + pb = [NSPasteboard pasteboardWithName:reinterpret_cast<const NSString *>(pbname)]; + CFRelease (pbname); } + if (pb) { + NSString *text = [pb stringForType:NSStringPboardType]; + if (text) + return qt_mac_NSStringToQString(text); + } + return QString(); } QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 62db064..f11ccc5 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -116,7 +116,7 @@ typedef struct CGPoint NSPoint; QT_BEGIN_NAMESPACE Qt::MouseButtons qt_mac_get_buttons(int buttons); Qt::MouseButton qt_mac_get_button(EventMouseButton button); -void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0); +void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0.15); bool macWindowIsTextured(void * /*OSWindowRef*/ window); void macWindowToolbarShow(const QWidget *widget, bool show ); void macWindowToolbarSet( void * /*OSWindowRef*/ window, void* toolbarRef ); @@ -170,7 +170,7 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list); void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow); CGFloat qt_mac_get_scalefactor(); -QString qt_mac_get_pasteboardString(); +QString qt_mac_get_pasteboardString(OSPasteboardRef paste); #ifdef __OBJC__ inline NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &qstrlist) diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index e25bc81..789d89e 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -124,6 +124,8 @@ public: static inline CAknTitlePane* titlePane(); static inline CAknContextPane* contextPane(); static inline CEikButtonGroupContainer* buttonGroupContainer(); + + TTrapHandler *s60InstalledTrapHandler; #endif }; diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index 61acbac..9f08dc6 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -428,6 +428,7 @@ struct QX11Data // true if Qt is compiled w/ MIT-SHM support and MIT-SHM is supported on the connected Display bool use_mitshm; + bool use_mitshm_pixmaps; int mitshm_major; // true if Qt is compiled w/ Tablet support and we have a tablet. diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index de08312..9165515 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -93,6 +93,7 @@ # include "qx11info_x11.h" #endif +#include <private/qgraphicseffect_p.h> #include <private/qwindowsurface_p.h> #include <private/qbackingstore_p.h> #ifdef Q_WS_MAC @@ -149,24 +150,6 @@ static inline bool hasBackingStoreSupport() #endif } -/*! - \internal - - Returns true if \a p or any of its parents enable the - Qt::BypassGraphicsProxyWidget window flag. Used in QWidget::show() and - QWidget::setParent() to determine whether it's necessary to embed the - widget into a QGraphicsProxyWidget or not. -*/ -static inline bool bypassGraphicsProxyWidget(QWidget *p) -{ - while (p) { - if (p->windowFlags() & Qt::BypassGraphicsProxyWidget) - return true; - p = p->parentWidget(); - } - return false; -} - #ifdef Q_WS_MAC # define QT_NO_PAINT_DEBUG #endif @@ -1566,7 +1549,9 @@ void QWidgetPrivate::createExtra() extra = new QWExtra; extra->glContext = 0; extra->topextra = 0; +#ifndef QT_NO_GRAPHICSVIEW extra->proxyWidget = 0; +#endif #ifndef QT_NO_CURSOR extra->curs = 0; #endif @@ -1716,12 +1701,13 @@ void QWidgetPrivate::propagatePaletteChange() { Q_Q(QWidget); // Propagate a new inherited mask to all children. - if (!q->parentWidget() && extra && extra->proxyWidget) { #ifndef QT_NO_GRAPHICSVIEW + if (!q->parentWidget() && extra && extra->proxyWidget) { QGraphicsProxyWidget *p = extra->proxyWidget; inheritedPaletteResolveMask = p->d_func()->inheritedPaletteResolveMask | p->palette().resolve(); + } else #endif //QT_NO_GRAPHICSVIEW - } else if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) { + if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) { inheritedPaletteResolveMask = 0; } int mask = data.pal.resolve() | inheritedPaletteResolveMask; @@ -1806,12 +1792,29 @@ QRegion QWidgetPrivate::clipRegion() const return r; } +void QWidgetPrivate::invalidateGraphicsEffectsRecursively() +{ + Q_Q(QWidget); + QWidget *w = q; + do { + if (w->graphicsEffect()) { + QWidgetEffectSourcePrivate *sourced = + static_cast<QWidgetEffectSourcePrivate *>(w->graphicsEffect()->source()->d_func()); + if (!sourced->updateDueToGraphicsEffect) + w->graphicsEffect()->source()->d_func()->invalidateCache(); + } + w = w->parentWidget(); + } while (w); +} + void QWidgetPrivate::setDirtyOpaqueRegion() { Q_Q(QWidget); dirtyOpaqueChildren = true; + invalidateGraphicsEffectsRecursively(); + if (q->isWindow()) return; @@ -1825,18 +1828,6 @@ void QWidgetPrivate::setDirtyOpaqueRegion() pd->setDirtyOpaqueRegion(); } -QRegion QWidgetPrivate::getOpaqueRegion() const -{ - Q_Q(const QWidget); - - QRegion r = isOpaque ? q->rect() : getOpaqueChildren(); - if (extra && extra->hasMask) - r &= extra->mask; - if (r.isEmpty()) - return r; - return r & clipRect(); -} - const QRegion &QWidgetPrivate::getOpaqueChildren() const { if (!dirtyOpaqueChildren) @@ -1851,9 +1842,17 @@ const QRegion &QWidgetPrivate::getOpaqueChildren() const continue; const QPoint offset = child->geometry().topLeft(); - that->opaqueChildren += child->d_func()->getOpaqueRegion().translated(offset); + QWidgetPrivate *childd = child->d_func(); + QRegion r = childd->isOpaque ? child->rect() : childd->getOpaqueChildren(); + if (childd->extra && childd->extra->hasMask) + r &= childd->extra->mask; + if (r.isEmpty()) + continue; + r.translate(offset); + that->opaqueChildren += r; } + that->opaqueChildren &= q_func()->rect(); that->dirtyOpaqueChildren = false; return that->opaqueChildren; @@ -3072,6 +3071,7 @@ void QWidgetPrivate::setEnabled_helper(bool enable) #if defined(Q_WS_MAC) setEnabled_helper_sys(enable); #endif +#ifndef QT_NO_IM if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) { QInputContext *qic = inputContext(); if (enable) { @@ -3081,6 +3081,7 @@ void QWidgetPrivate::setEnabled_helper(bool enable) qic->setFocusWidget(0); } } +#endif //QT_NO_IM QEvent e(QEvent::EnabledChange); QApplication::sendEvent(q, &e); #ifdef QT3_SUPPORT @@ -4379,7 +4380,11 @@ QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const Q_Q(const QWidget); QPalette naturalPalette = QApplication::palette(q); if (!q->testAttribute(Qt::WA_StyleSheet) - && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation) || (extra && extra->proxyWidget))) { + && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation) +#ifndef QT_NO_GRAPHICSVIEW + || (extra && extra->proxyWidget) +#endif //QT_NO_GRAPHICSVIEW + )) { if (QWidget *p = q->parentWidget()) { if (!p->testAttribute(Qt::WA_StyleSheet)) { if (!naturalPalette.isCopyOf(QApplication::palette())) { @@ -4390,13 +4395,14 @@ QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const naturalPalette = p->palette(); } } - } else if (extra && extra->proxyWidget) { + } #ifndef QT_NO_GRAPHICSVIEW + else if (extra && extra->proxyWidget) { QPalette inheritedPalette = extra->proxyWidget->palette(); inheritedPalette.resolve(inheritedMask); naturalPalette = inheritedPalette.resolve(naturalPalette); -#endif //QT_NO_GRAPHICSVIEW } +#endif //QT_NO_GRAPHICSVIEW } naturalPalette.resolve(0); return naturalPalette; @@ -4514,7 +4520,11 @@ QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const Q_Q(const QWidget); QFont naturalFont = QApplication::font(q); if (!q->testAttribute(Qt::WA_StyleSheet) - && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation) || (extra && extra->proxyWidget))) { + && (!q->isWindow() || q->testAttribute(Qt::WA_WindowPropagation) +#ifndef QT_NO_GRAPHICSVIEW + || (extra && extra->proxyWidget) +#endif //QT_NO_GRAPHICSVIEW + )) { if (QWidget *p = q->parentWidget()) { if (!p->testAttribute(Qt::WA_StyleSheet)) { if (!naturalFont.isCopyOf(QApplication::font())) { @@ -4525,13 +4535,14 @@ QFont QWidgetPrivate::naturalWidgetFont(uint inheritedMask) const naturalFont = p->font(); } } - } else if (extra && extra->proxyWidget) { + } #ifndef QT_NO_GRAPHICSVIEW + else if (extra && extra->proxyWidget) { QFont inheritedFont = extra->proxyWidget->font(); inheritedFont.resolve(inheritedMask); naturalFont = inheritedFont.resolve(naturalFont); -#endif //QT_NO_GRAPHICSVIEW } +#endif //QT_NO_GRAPHICSVIEW } naturalFont.resolve(0); return naturalFont; @@ -4578,12 +4589,13 @@ void QWidgetPrivate::updateFont(const QFont &font) data.fnt.x11SetScreen(xinfo.screen()); #endif // Combine new mask with natural mask and propagate to children. - if (!q->parentWidget() && extra && extra->proxyWidget) { #ifndef QT_NO_GRAPHICSVIEW + if (!q->parentWidget() && extra && extra->proxyWidget) { QGraphicsProxyWidget *p = extra->proxyWidget; inheritedFontResolveMask = p->d_func()->inheritedFontResolveMask | p->font().resolve(); + } else #endif //QT_NO_GRAPHICSVIEW - } else if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) { + if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation)) { inheritedFontResolveMask = 0; } uint newMask = data.fnt.resolve() | inheritedFontResolveMask; @@ -5215,6 +5227,10 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP paintEngine->d_func()->systemClip = QRegion(); } else { context.painter = sharedPainter; + if (sharedPainter->worldTransform() != sourced->lastEffectTransform) { + sourced->invalidateCache(); + sourced->lastEffectTransform = sharedPainter->worldTransform(); + } sharedPainter->save(); sharedPainter->translate(offset); graphicsEffect->draw(sharedPainter, source); @@ -5390,7 +5406,11 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis , sharedPainter, backingStore); } - if (w->updatesEnabled() && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget)) { + if (w->updatesEnabled() +#ifndef QT_NO_GRAPHICSVIEW + && (!w->d_func()->extra || !w->d_func()->extra->proxyWidget) +#endif //QT_NO_GRAPHICSVIEW + ) { QRegion wRegion(rgn); wRegion &= wd->effectiveRectFor(w->data->crect); wRegion.translate(-widgetPos); @@ -5433,7 +5453,8 @@ void QWidgetEffectSourcePrivate::draw(QPainter *painter) context->sharedPainter, context->backingStore); } -QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const +QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const { const bool deviceCoordinates = (system == Qt::DeviceCoordinates); if (!context && deviceCoordinates) { @@ -5451,7 +5472,20 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * pixmapOffset = painterTransform.map(pixmapOffset); } - QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + + QRect effectRect; + + if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) { + effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + + } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) { + effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect(); + + } else { + effectRect = sourceRect.toAlignedRect(); + + } + if (offset) *offset = effectRect.topLeft(); @@ -5487,6 +5521,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * return pixmap; } +#ifndef QT_NO_GRAPHICSVIEW /*! \internal @@ -5495,7 +5530,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * If successful, the function returns the proxy that embeds the widget, or 0 if no embedded widget was found. */ -QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(QWidget *origin) +QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin) { if (origin) { QWExtra *extra = origin->d_func()->extra; @@ -5505,6 +5540,7 @@ QGraphicsProxyWidget * QWidgetPrivate::nearestGraphicsProxyWidget(QWidget *origi } return 0; } +#endif /*! \property QWidget::locale @@ -7314,7 +7350,7 @@ void QWidget::setVisible(bool visible) break; parent = parent->parentWidget(); } - if (parent && !d->getOpaqueRegion().isEmpty()) + if (parent) parent->d_func()->setDirtyOpaqueRegion(); } @@ -7739,6 +7775,10 @@ void QWidget::adjustSize() Q_D(QWidget); ensurePolished(); QSize s = d->adjustedSize(); + + if (d->layout) + d->layout->activate(); + if (s.isValid()) resize(s); } @@ -8940,11 +8980,16 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const Qt::InputMethodHints QWidget::inputMethodHints() const { Q_D(const QWidget); +#ifndef QT_NO_IM return d->imHints; +#else //QT_NO_IM + return 0; +#endif //QT_NO_IM } void QWidget::setInputMethodHints(Qt::InputMethodHints hints) { +#ifndef QT_NO_IM Q_D(QWidget); d->imHints = hints; // Optimisation to update input context only it has already been created. @@ -8953,6 +8998,7 @@ void QWidget::setInputMethodHints(Qt::InputMethodHints hints) if (ic) ic->update(); } +#endif //QT_NO_IM } @@ -10284,6 +10330,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) QApplication::sendEvent(this, &e); break; } case Qt::WA_NativeWindow: { +#ifndef QT_NO_IM QInputContext *ic = 0; if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) { ic = d->inputContext(); @@ -10296,6 +10343,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->createWinId(); if (ic && isEnabled()) ic->setFocusWidget(this); +#endif //QT_NO_IM break; } case Qt::WA_PaintOnScreen: @@ -10325,6 +10373,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) #endif break; case Qt::WA_InputMethodEnabled: { +#ifndef QT_NO_IM QInputContext *ic = d->ic; if (!ic && (!on || hasFocus())) ic = d->inputContext(); @@ -10336,6 +10385,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) ic->setFocusWidget(0); } } +#endif //QT_NO_IM break; } case Qt::WA_WindowPropagation: @@ -11698,6 +11748,22 @@ void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureContext context) (void)QGestureManager::instance(); // create a gesture manager } +/*! + Unsubscribes the widget to a given \a gesture type + + \sa QGestureEvent + \since 4.6 +*/ +void QWidget::ungrabGesture(Qt::GestureType gesture) +{ + Q_D(QWidget); + if (d->gestureContext.remove(gesture)) { + QGestureManager *manager = QGestureManager::instance(); + manager->cleanupCachedGestures(this, gesture); + } +} + + QT_END_NAMESPACE #include "moc_qwidget.cpp" diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index e603a1a..fce3f09 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -355,6 +355,7 @@ public: void setGraphicsEffect(QGraphicsEffect *effect); void grabGesture(Qt::GestureType type, Qt::GestureContext context = Qt::WidgetWithChildrenGesture); + void ungrabGesture(Qt::GestureType type); public Q_SLOTS: void setWindowTitle(const QString &); diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 05c6a5b..58252ca 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2896,6 +2896,7 @@ void QWidgetPrivate::setCursor_sys(const QCursor &) #else Q_Q(QWidget); if (q->testAttribute(Qt::WA_WState_Created)) { + QMacCocoaAutoReleasePool pool; [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; } #endif @@ -2908,6 +2909,7 @@ void QWidgetPrivate::unsetCursor_sys() #else Q_Q(QWidget); if (q->testAttribute(Qt::WA_WState_Created)) { + QMacCocoaAutoReleasePool pool; [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; } #endif @@ -3048,6 +3050,7 @@ void QWidget::grabMouse() } } +#ifndef QT_NO_CURSOR void QWidget::grabMouse(const QCursor &) { if(isVisible() && !qt_nograb()) { @@ -3056,6 +3059,7 @@ void QWidget::grabMouse(const QCursor &) mac_mouse_grabber=this; } } +#endif void QWidget::releaseMouse() { @@ -3388,12 +3392,19 @@ void QWidgetPrivate::hide_sys() w = q->parentWidget()->window(); if(!w || (!w->isVisible() && !w->isMinimized())) { #ifndef QT_MAC_USE_COCOA - for(WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true); - wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) { + for (WindowPtr wp = GetFrontWindowOfClass(kMovableModalWindowClass, true); + wp; wp = GetNextWindowOfClass(wp, kMovableModalWindowClass, true)) { if((w = qt_mac_find_window(wp))) break; } if (!w){ + for (WindowPtr wp = GetFrontWindowOfClass(kDocumentWindowClass, true); + wp; wp = GetNextWindowOfClass(wp, kDocumentWindowClass, true)) { + if((w = qt_mac_find_window(wp))) + break; + } + } + if (!w){ for(WindowPtr wp = GetFrontWindowOfClass(kSimpleWindowClass, true); wp; wp = GetNextWindowOfClass(wp, kSimpleWindowClass, true)) { if((w = qt_mac_find_window(wp))) diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index f7c2712..73a7d68 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -63,7 +63,9 @@ #include "QtGui/qstyle.h" #include "QtGui/qapplication.h" #include <private/qgraphicseffect_p.h> - +#include "QtGui/qgraphicsproxywidget.h" +#include "QtGui/qgraphicsscene.h" +#include "QtGui/qgraphicsview.h" #include <private/qgesture_p.h> #ifdef Q_WS_WIN @@ -180,7 +182,9 @@ struct QWExtra { // Regular pointers (keep them together to avoid gaps on 64 bits architectures). void *glContext; // if the widget is hijacked by QGLWindowSurface QTLWExtra *topextra; // only useful for TLWs +#ifndef QT_NO_GRAPHICSVIEW QGraphicsProxyWidget *proxyWidget; // if the widget is embedded +#endif #ifndef QT_NO_CURSOR QCursor *curs; #endif @@ -235,6 +239,24 @@ struct QWExtra { #endif }; +/*! + \internal + + Returns true if \a p or any of its parents enable the + Qt::BypassGraphicsProxyWidget window flag. Used in QWidget::show() and + QWidget::setParent() to determine whether it's necessary to embed the + widget into a QGraphicsProxyWidget or not. +*/ +static inline bool bypassGraphicsProxyWidget(const QWidget *p) +{ + while (p) { + if (p->windowFlags() & Qt::BypassGraphicsProxyWidget) + return true; + p = p->parentWidget(); + } + return false; +} + class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QWidget) @@ -345,7 +367,9 @@ public: QPainter *beginSharedPainter(); bool endSharedPainter(); - static QGraphicsProxyWidget * nearestGraphicsProxyWidget(QWidget *origin); +#ifndef QT_NO_GRAPHICSVIEW + static QGraphicsProxyWidget * nearestGraphicsProxyWidget(const QWidget *origin); +#endif QWindowSurface *createDefaultWindowSurface(); QWindowSurface *createDefaultWindowSurface_sys(); void repaint_sys(const QRegion &rgn); @@ -360,8 +384,8 @@ public: void setOpaque(bool opaque); void updateIsTranslucent(); bool paintOnScreen() const; + void invalidateGraphicsEffectsRecursively(); - QRegion getOpaqueRegion() const; const QRegion &getOpaqueChildren() const; void setDirtyOpaqueRegion(); @@ -442,6 +466,31 @@ public: void setModal_sys(); + // This is an helper function that return the available geometry for + // a widget and takes care is this one is in QGraphicsView. + // If the widget is not embed in a scene then the geometry available is + // null, we let QDesktopWidget decide for us. + static QRect screenGeometry(const QWidget *widget) + { + QRect screen; +#ifndef QT_NO_GRAPHICSVIEW + QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget); + //It's embedded if it has an ancestor + if (ancestorProxy) { + if (!bypassGraphicsProxyWidget(widget)) { + // One view, let be smart and return the viewport rect then the popup is aligned + if (ancestorProxy->scene()->views().size() == 1) { + QGraphicsView *view = ancestorProxy->scene()->views().at(0); + screen = view->mapToScene(view->viewport()->rect()).boundingRect().toRect(); + } else { + screen = ancestorProxy->scene()->sceneRect().toRect(); + } + } + } +#endif + return screen; + } + inline void setRedirected(QPaintDevice *replacement, const QPoint &offset) { Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent)); @@ -729,7 +778,7 @@ class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate { public: QWidgetEffectSourcePrivate(QWidget *widget) - : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0) + : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0), updateDueToGraphicsEffect(false) {} inline void detach() @@ -742,7 +791,11 @@ public: { return m_widget; } inline void update() - { m_widget->update(); } + { + updateDueToGraphicsEffect = true; + m_widget->update(); + updateDueToGraphicsEffect = false; + } inline bool isPixmap() const { return false; } @@ -754,7 +807,7 @@ public: if (QWidget *parent = m_widget->parentWidget()) parent->update(); else - m_widget->update(); + update(); } inline const QStyleOption *styleOption() const @@ -765,10 +818,13 @@ public: QRectF boundingRect(Qt::CoordinateSystem system) const; void draw(QPainter *p); - QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const; + QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset, + QGraphicsEffectSource::PixmapPadMode mode) const; QWidget *m_widget; QWidgetPaintContext *context; + QTransform lastEffectTransform; + bool updateDueToGraphicsEffect; }; inline QWExtra *QWidgetPrivate::extraData() const diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index 0f46016..e299c6e 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -280,7 +280,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) QApplicationPrivate::leaveModal(this); else if ((windowType() == Qt::Popup)) qApp->d_func()->closePopup(this); - +#ifndef QT_NO_IM if (d->ic) { delete d->ic; d->ic =0; @@ -291,6 +291,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (qic) qic->widgetDestroyed(this); } +#endif //QT_NO_IM if ((windowType() == Qt::Desktop)) { } else { diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index abf5ba5..a6d8ed7 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -564,8 +564,13 @@ void QWidgetPrivate::lower_sys() Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - if (q->internalWinId()) - q->internalWinId()->DrawableWindow()->SetOrdinalPosition(-1); + if (q->internalWinId()) { + // If toplevel widget, lower app to background + if (q->isWindow()) + S60->wsSession().SetWindowGroupOrdinalPosition(S60->windowGroup().Identifier(), -1); + else + q->internalWinId()->DrawableWindow()->SetOrdinalPosition(-1); + } if (!q->isWindow()) invalidateBuffer(q->rect()); @@ -711,62 +716,6 @@ void QWidgetPrivate::s60UpdateIsOpaque() window->SetTransparentRegion(TRegionFix<1>()); } -CFbsBitmap* qt_pixmapToNativeBitmap(QPixmap pixmap, bool invert) -{ - CFbsBitmap* fbsBitmap = q_check_ptr(new CFbsBitmap); // CBase derived object needs check on new - TSize size(pixmap.size().width(), pixmap.size().height()); - TDisplayMode mode(EColor16MU); - - bool isNull = pixmap.isNull(); - int depth = pixmap.depth(); - - // TODO: dummy assumptions from bit amounts for each color - // Will fix later on when native pixmap is implemented - switch(pixmap.depth()) { - case 1: - mode = EGray2; - break; - case 4: - mode = EColor16; - break; - case 8: - mode = EColor256; - break; - case 12: - mode = EColor4K; - break; - case 16: - mode = EColor64K; - break; - case 24: - mode = EColor16M; - break; - case 32: - case EColor16MU: - break; - default: - qFatal("Unsupported pixmap depth"); - break; - } - - qt_symbian_throwIfError(fbsBitmap->Create(size, mode)); - fbsBitmap->LockHeap(); - QImage image = pixmap.toImage(); - - if (invert) - image.invertPixels(); - - int height = pixmap.size().height(); - for(int i=0;i<height;i++ ) - { - TPtr8 scanline(image.scanLine(i), image.bytesPerLine(), image.bytesPerLine()); - fbsBitmap->SetScanLine( scanline, i ); - } - - fbsBitmap->UnlockHeap(); - return fbsBitmap; -} - void QWidgetPrivate::setWindowIcon_sys(bool forceReset) { #ifdef Q_WS_S60 @@ -795,12 +744,8 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) mask.fill(Qt::color1); } - // Convert to CFbsBitmp - // TODO: When QPixmap is adapted to use native CFbsBitmap, - // it could be set directly to context pane - CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false); - CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true); - + CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap(); + CFbsBitmap* nMask = mask.toSymbianCFbsBitmap(); contextPane->SetPicture(nBitmap,nMask); } else { // Icon set to null -> set context pane picture to default @@ -831,12 +776,8 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) mask.fill(Qt::color1); } - // Convert to CFbsBitmp - // TODO: When QPixmap is adapted to use native CFbsBitmap, - // it could be set directly to context pane - CFbsBitmap* nBitmap = qt_pixmapToNativeBitmap(pm, false); - CFbsBitmap* nMask = qt_pixmapToNativeBitmap(mask, true); - + CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap(); + CFbsBitmap* nMask = mask.toSymbianCFbsBitmap(); titlePane->SetSmallPicture( nBitmap, nMask, ETrue ); } else { // Icon set to null -> set context pane picture to default diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 2b11bec..5bf7649 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -161,6 +161,9 @@ static void qt_tablet_init() qt_tablet_widget = new QWidget(0); qt_tablet_widget->createWinId(); qt_tablet_widget->setObjectName(QLatin1String("Qt internal tablet widget")); + // We dont need this internal widget to appear in QApplication::topLevelWidgets() + if (QWidgetPrivate::allWidgets) + QWidgetPrivate::allWidgets->remove(qt_tablet_widget); LOGCONTEXT lcMine; qAddPostRoutine(qt_tablet_cleanup); struct tagAXIS tpOri[3]; @@ -851,10 +854,13 @@ void QWidget::grabMouse() Q_ASSERT(testAttribute(Qt::WA_WState_Created)); SetCapture(effectiveWinId()); mouseGrb = this; +#ifndef QT_NO_CURSOR mouseGrbCur = new QCursor(mouseGrb->cursor()); +#endif } } +#ifndef QT_NO_CURSOR void QWidget::grabMouse(const QCursor &cursor) { if (!qt_nograb()) { @@ -868,6 +874,7 @@ void QWidget::grabMouse(const QCursor &cursor) mouseGrb = this; } } +#endif void QWidget::releaseMouse() { diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 663178f..28676da 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -950,7 +950,7 @@ static void qt_x11_recreateWidget(QWidget *widget) static void qt_x11_recreateNativeWidgetsRecursive(QWidget *widget) { - if (widget->testAttribute(Qt::WA_NativeWindow)) + if (widget->internalWinId()) qt_x11_recreateWidget(widget); const QObjectList &children = widget->children(); diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp index 4619594..12d3058 100644 --- a/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp +++ b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp @@ -97,11 +97,11 @@ QGestureRecognizer::Result QWinNativePanGestureRecognizer::filterEvent(QGesture return QGestureRecognizer::Ignore; } if (q->state() == Qt::NoGesture) { - d->lastOffset = d->totalOffset = d->offset = QSize(); + d->lastOffset = d->totalOffset = d->offset = QPointF(); } else { d->lastOffset = d->offset; - d->offset = QSize(ev->position.x() - d->lastPosition.x(), - ev->position.y() - d->lastPosition.y()); + d->offset = QPointF(ev->position.x() - d->lastPosition.x(), + ev->position.y() - d->lastPosition.y()); d->totalOffset += d->offset; } d->lastPosition = ev->position; @@ -114,7 +114,7 @@ void QWinNativePanGestureRecognizer::reset(QGesture *state) QPanGesture *pan = static_cast<QPanGesture*>(state); QPanGesturePrivate *d = pan->d_func(); - d->totalOffset = d->lastOffset = d->offset = QSizeF(); + d->totalOffset = d->lastOffset = d->offset = QPointF(); d->lastPosition = QPoint(); d->acceleration = 0; diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp index d211229..aa98536 100644 --- a/src/gui/math3d/qgenericmatrix.cpp +++ b/src/gui/math3d/qgenericmatrix.cpp @@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE The contents of the array \a values is assumed to be in row-major order. - \sa toValueArray() + \sa copyDataTo() */ /*! @@ -102,11 +102,11 @@ QT_BEGIN_NAMESPACE Returns true if this matrix is the identity; false otherwise. - \sa setIdentity() + \sa setToIdentity() */ /*! - \fn void QGenericMatrix::setIdentity() + \fn void QGenericMatrix::setToIdentity() Sets this matrix to the identity. @@ -213,9 +213,9 @@ QT_BEGIN_NAMESPACE */ /*! - \fn void QGenericMatrix::toValueArray(T *values) + \fn void QGenericMatrix::copyDataTo(T *values) const - Retrieves the N * M items in this matrix and writes them to \a values + Retrieves the N * M items in this matrix and copies them to \a values in row-major order. */ @@ -243,4 +243,100 @@ QT_BEGIN_NAMESPACE \sa data() */ +#ifndef QT_NO_DATASTREAM + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QGenericMatrix<N, M, T> &matrix) + \relates QGenericMatrix + + Writes the given \a matrix to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QGenericMatrix<N, M, T> &matrix) + \relates QGenericMatrix + + Reads a NxM matrix from the given \a stream into the given \a matrix + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +#endif + +/*! + \typedef QMatrix2x2 + \relates QGenericMatrix + + The QMatrix2x2 type defines a convenient instantiation of the + QGenericMatrix template for 2 columns, 2 rows, and qreal as + the element type. +*/ + +/*! + \typedef QMatrix2x3 + \relates QGenericMatrix + + The QMatrix2x3 type defines a convenient instantiation of the + QGenericMatrix template for 2 columns, 3 rows, and qreal as + the element type. +*/ + +/*! + \typedef QMatrix2x4 + \relates QGenericMatrix + + The QMatrix2x4 type defines a convenient instantiation of the + QGenericMatrix template for 2 columns, 4 rows, and qreal as + the element type. +*/ + +/*! + \typedef QMatrix3x2 + \relates QGenericMatrix + + The QMatrix3x2 type defines a convenient instantiation of the + QGenericMatrix template for 3 columns, 2 rows, and qreal as + the element type. +*/ + +/*! + \typedef QMatrix3x3 + \relates QGenericMatrix + + The QMatrix3x3 type defines a convenient instantiation of the + QGenericMatrix template for 3 columns, 3 rows, and qreal as + the element type. +*/ + +/*! + \typedef QMatrix3x4 + \relates QGenericMatrix + + The QMatrix3x4 type defines a convenient instantiation of the + QGenericMatrix template for 3 columns, 4 rows, and qreal as + the element type. +*/ + +/*! + \typedef QMatrix4x2 + \relates QGenericMatrix + + The QMatrix4x2 type defines a convenient instantiation of the + QGenericMatrix template for 4 columns, 2 rows, and qreal as + the element type. +*/ + +/*! + \typedef QMatrix4x3 + \relates QGenericMatrix + + The QMatrix4x3 type defines a convenient instantiation of the + QGenericMatrix template for 4 columns, 3 rows, and qreal as + the element type. +*/ + QT_END_NAMESPACE diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index f178d02..3871754 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -44,6 +44,7 @@ #include <QtCore/qmetatype.h> #include <QtCore/qdebug.h> +#include <QtCore/qdatastream.h> QT_BEGIN_HEADER @@ -63,7 +64,7 @@ public: T& operator()(int row, int column); bool isIdentity() const; - void setIdentity(); + void setToIdentity(); void fill(T value); @@ -76,7 +77,7 @@ public: bool operator==(const QGenericMatrix<N, M, T>& other) const; bool operator!=(const QGenericMatrix<N, M, T>& other) const; - void toValueArray(T *values); + void copyDataTo(T *values) const; T *data() { return m[0]; } const T *data() const { return m[0]; } @@ -113,7 +114,7 @@ private: template <int N, int M, typename T> Q_INLINE_TEMPLATE QGenericMatrix<N, M, T>::QGenericMatrix() { - setIdentity(); + setToIdentity(); } template <int N, int M, typename T> @@ -164,7 +165,7 @@ Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T>::isIdentity() const } template <int N, int M, typename T> -Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T>::setIdentity() +Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T>::setToIdentity() { for (int col = 0; col < N; ++col) { for (int row = 0; row < M; ++row) { @@ -316,7 +317,7 @@ Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T> operator/(const QGenericMatrix<N, M } template <int N, int M, typename T> -Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T>::toValueArray(T *values) +Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T>::copyDataTo(T *values) const { for (int col = 0; col < N; ++col) for (int row = 0; row < M; ++row) @@ -352,6 +353,32 @@ QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T> &m) #endif +#ifndef QT_NO_DATASTREAM + +template <int N, int M, typename T> +QDataStream &operator<<(QDataStream &stream, const QGenericMatrix<N, M, T> &matrix) +{ + for (int row = 0; row < M; ++row) + for (int col = 0; col < N; ++col) + stream << double(matrix(row, col)); + return stream; +} + +template <int N, int M, typename T> +QDataStream &operator>>(QDataStream &stream, QGenericMatrix<N, M, T> &matrix) +{ + double x; + for (int row = 0; row < M; ++row) { + for (int col = 0; col < N; ++col) { + stream >> x; + matrix(row, col) = T(x); + } + } + return stream; +} + +#endif + QT_END_NAMESPACE Q_DECLARE_METATYPE(QMatrix2x2) diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index ed1b13d..2c3d616 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE \sa QVector3D, QGenericMatrix */ +static const qreal inv_dist_to_plane = 1. / 1024.; + /*! \fn QMatrix4x4::QMatrix4x4() @@ -71,10 +73,10 @@ QT_BEGIN_NAMESPACE If the matrix has a special type (identity, translate, scale, etc), the programmer should follow this constructor with a call to - inferSpecialType() if they wish QMatrix4x4 to optimize further + optimize() if they wish QMatrix4x4 to optimize further calls to translate(), scale(), etc. - \sa toValueArray(), inferSpecialType() + \sa copyDataTo(), optimize() */ QMatrix4x4::QMatrix4x4(const qreal *values) { @@ -94,10 +96,10 @@ QMatrix4x4::QMatrix4x4(const qreal *values) If the matrix has a special type (identity, translate, scale, etc), the programmer should follow this constructor with a call to - inferSpecialType() if they wish QMatrix4x4 to optimize further + optimize() if they wish QMatrix4x4 to optimize further calls to translate(), scale(), etc. - \sa inferSpecialType() + \sa optimize() */ #if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC) @@ -174,10 +176,10 @@ QMatrix4x4::QMatrix4x4(const qreal *values, int cols, int rows) If \a matrix has a special type (identity, translate, scale, etc), the programmer should follow this constructor with a call to - inferSpecialType() if they wish QMatrix4x4 to optimize further + optimize() if they wish QMatrix4x4 to optimize further calls to translate(), scale(), etc. - \sa toAffine(), inferSpecialType() + \sa toAffine(), optimize() */ QMatrix4x4::QMatrix4x4(const QMatrix& matrix) { @@ -206,10 +208,10 @@ QMatrix4x4::QMatrix4x4(const QMatrix& matrix) If \a transform has a special type (identity, translate, scale, etc), the programmer should follow this constructor with a call to - inferSpecialType() if they wish QMatrix4x4 to optimize further + optimize() if they wish QMatrix4x4 to optimize further calls to translate(), scale(), etc. - \sa toTransform(), inferSpecialType() + \sa toTransform(), optimize() */ QMatrix4x4::QMatrix4x4(const QTransform& transform) { @@ -247,7 +249,7 @@ QMatrix4x4::QMatrix4x4(const QTransform& transform) Returns a reference to the element at position (\a row, \a column) in this matrix so that the element can be assigned to. - \sa inferSpecialType(), setColumn(), setRow() + \sa optimize(), setColumn(), setRow() */ /*! @@ -287,11 +289,11 @@ QMatrix4x4::QMatrix4x4(const QTransform& transform) Returns true if this matrix is the identity; false otherwise. - \sa setIdentity() + \sa setToIdentity() */ /*! - \fn void QMatrix4x4::setIdentity() + \fn void QMatrix4x4::setToIdentity() Sets this matrix to the identity. @@ -692,11 +694,11 @@ QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor) /*! Multiplies this matrix by another that scales coordinates by - the components of \a vector. Returns this matrix. + the components of \a vector. \sa translate(), rotate() */ -QMatrix4x4& QMatrix4x4::scale(const QVector3D& vector) +void QMatrix4x4::scale(const QVector3D& vector) { qreal vx = vector.x(); qreal vy = vector.y(); @@ -730,7 +732,6 @@ QMatrix4x4& QMatrix4x4::scale(const QVector3D& vector) m[2][3] *= vz; flagBits = General; } - return *this; } #endif @@ -738,11 +739,11 @@ QMatrix4x4& QMatrix4x4::scale(const QVector3D& vector) \overload Multiplies this matrix by another that scales coordinates by the - components \a x, and \a y. Returns this matrix. + components \a x, and \a y. \sa translate(), rotate() */ -QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y) +void QMatrix4x4::scale(qreal x, qreal y) { if (flagBits == Identity) { m[0][0] = x; @@ -766,18 +767,17 @@ QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y) m[1][3] *= y; flagBits = General; } - return *this; } /*! \overload Multiplies this matrix by another that scales coordinates by the - components \a x, \a y, and \a z. Returns this matrix. + components \a x, \a y, and \a z. \sa translate(), rotate() */ -QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y, qreal z) +void QMatrix4x4::scale(qreal x, qreal y, qreal z) { if (flagBits == Identity) { m[0][0] = x; @@ -808,18 +808,17 @@ QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y, qreal z) m[2][3] *= z; flagBits = General; } - return *this; } /*! \overload Multiplies this matrix by another that scales coordinates by the - given \a factor. Returns this matrix. + given \a factor. \sa translate(), rotate() */ -QMatrix4x4& QMatrix4x4::scale(qreal factor) +void QMatrix4x4::scale(qreal factor) { if (flagBits == Identity) { m[0][0] = factor; @@ -850,17 +849,16 @@ QMatrix4x4& QMatrix4x4::scale(qreal factor) m[2][3] *= factor; flagBits = General; } - return *this; } #ifndef QT_NO_VECTOR3D /*! Multiplies this matrix by another that translates coordinates by - the components of \a vector. Returns this matrix. + the components of \a vector. \sa scale(), rotate() */ -QMatrix4x4& QMatrix4x4::translate(const QVector3D& vector) +void QMatrix4x4::translate(const QVector3D& vector) { qreal vx = vector.x(); qreal vy = vector.y(); @@ -893,7 +891,6 @@ QMatrix4x4& QMatrix4x4::translate(const QVector3D& vector) else if (flagBits != (Rotation | Translation)) flagBits = General; } - return *this; } #endif @@ -902,11 +899,11 @@ QMatrix4x4& QMatrix4x4::translate(const QVector3D& vector) \overload Multiplies this matrix by another that translates coordinates - by the components \a x, and \a y. Returns this matrix. + by the components \a x, and \a y. \sa scale(), rotate() */ -QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y) +void QMatrix4x4::translate(qreal x, qreal y) { if (flagBits == Identity) { m[3][0] = x; @@ -933,18 +930,17 @@ QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y) else if (flagBits != (Rotation | Translation)) flagBits = General; } - return *this; } /*! \overload Multiplies this matrix by another that translates coordinates - by the components \a x, \a y, and \a z. Returns this matrix. + by the components \a x, \a y, and \a z. \sa scale(), rotate() */ -QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y, qreal z) +void QMatrix4x4::translate(qreal x, qreal y, qreal z) { if (flagBits == Identity) { m[3][0] = x; @@ -974,20 +970,19 @@ QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y, qreal z) else if (flagBits != (Rotation | Translation)) flagBits = General; } - return *this; } #ifndef QT_NO_VECTOR3D /*! Multiples this matrix by another that rotates coordinates through - \a angle degrees about \a vector. Returns this matrix. + \a angle degrees about \a vector. \sa scale(), translate() */ -QMatrix4x4& QMatrix4x4::rotate(qreal angle, const QVector3D& vector) +void QMatrix4x4::rotate(qreal angle, const QVector3D& vector) { - return rotate(angle, vector.x(), vector.y(), vector.z()); + rotate(angle, vector.x(), vector.y(), vector.z()); } #endif @@ -996,14 +991,14 @@ QMatrix4x4& QMatrix4x4::rotate(qreal angle, const QVector3D& vector) \overload Multiplies this matrix by another that rotates coordinates through - \a angle degrees about the vector (\a x, \a y, \a z). Returns this matrix. + \a angle degrees about the vector (\a x, \a y, \a z). \sa scale(), translate() */ -QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z) +void QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z) { if (angle == 0.0f) - return *this; + return; QMatrix4x4 m(1); // The "1" says to not load the identity. qreal c, s, ic; if (angle == 90.0f || angle == -270.0f) { @@ -1025,7 +1020,7 @@ QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z) if (y == 0.0f) { if (z != 0.0f) { // Rotate around the Z axis. - m.setIdentity(); + m.setToIdentity(); m.m[0][0] = c; m.m[1][1] = c; if (z < 0.0f) { @@ -1040,7 +1035,7 @@ QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z) } } else if (z == 0.0f) { // Rotate around the Y axis. - m.setIdentity(); + m.setToIdentity(); m.m[0][0] = c; m.m[2][2] = c; if (y < 0.0f) { @@ -1055,7 +1050,7 @@ QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z) } } else if (y == 0.0f && z == 0.0f) { // Rotate around the X axis. - m.setIdentity(); + m.setToIdentity(); m.m[1][1] = c; m.m[2][2] = c; if (x < 0.0f) { @@ -1100,19 +1095,121 @@ QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z) flagBits = flags | Rotation; else flagBits = Rotation; - return *this; } -#ifndef QT_NO_VECTOR4D +/*! + \internal +*/ +void QMatrix4x4::projectedRotate(qreal angle, qreal x, qreal y, qreal z) +{ + // Used by QGraphicsRotation::applyTo() to perform a rotation + // and projection back to 2D in a single step. + if (angle == 0.0f) + return; + QMatrix4x4 m(1); // The "1" says to not load the identity. + qreal c, s, ic; + if (angle == 90.0f || angle == -270.0f) { + s = 1.0f; + c = 0.0f; + } else if (angle == -90.0f || angle == 270.0f) { + s = -1.0f; + c = 0.0f; + } else if (angle == 180.0f || angle == -180.0f) { + s = 0.0f; + c = -1.0f; + } else { + qreal a = angle * M_PI / 180.0f; + c = qCos(a); + s = qSin(a); + } + bool quick = false; + if (x == 0.0f) { + if (y == 0.0f) { + if (z != 0.0f) { + // Rotate around the Z axis. + m.setToIdentity(); + m.m[0][0] = c; + m.m[1][1] = c; + if (z < 0.0f) { + m.m[1][0] = s; + m.m[0][1] = -s; + } else { + m.m[1][0] = -s; + m.m[0][1] = s; + } + m.flagBits = General; + quick = true; + } + } else if (z == 0.0f) { + // Rotate around the Y axis. + m.setToIdentity(); + m.m[0][0] = c; + m.m[2][2] = 1.0f; + if (y < 0.0f) { + m.m[0][3] = -s * inv_dist_to_plane; + } else { + m.m[0][3] = s * inv_dist_to_plane; + } + m.flagBits = General; + quick = true; + } + } else if (y == 0.0f && z == 0.0f) { + // Rotate around the X axis. + m.setToIdentity(); + m.m[1][1] = c; + m.m[2][2] = 1.0f; + if (x < 0.0f) { + m.m[1][3] = s * inv_dist_to_plane; + } else { + m.m[1][3] = -s * inv_dist_to_plane; + } + m.flagBits = General; + quick = true; + } + if (!quick) { + qreal len = x * x + y * y + z * z; + if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) { + len = qSqrt(len); + x /= len; + y /= len; + z /= len; + } + ic = 1.0f - c; + m.m[0][0] = x * x * ic + c; + m.m[1][0] = x * y * ic - z * s; + m.m[2][0] = 0.0f; + m.m[3][0] = 0.0f; + m.m[0][1] = y * x * ic + z * s; + m.m[1][1] = y * y * ic + c; + m.m[2][1] = 0.0f; + m.m[3][1] = 0.0f; + m.m[0][2] = 0.0f; + m.m[1][2] = 0.0f; + m.m[2][2] = 1.0f; + m.m[3][2] = 0.0f; + m.m[0][3] = (x * z * ic - y * s) * -inv_dist_to_plane; + m.m[1][3] = (y * z * ic + x * s) * -inv_dist_to_plane; + m.m[2][3] = 0.0f; + m.m[3][3] = 1.0f; + } + int flags = flagBits; + *this *= m; + if (flags != Identity) + flagBits = flags | Rotation; + else + flagBits = Rotation; +} + +#ifndef QT_NO_QUATERNION /*! Multiples this matrix by another that rotates coordinates according to a specified \a quaternion. The \a quaternion is assumed to have - been normalized. Returns this matrix. + been normalized. \sa scale(), translate(), QQuaternion */ -QMatrix4x4& QMatrix4x4::rotate(const QQuaternion& quaternion) +void QMatrix4x4::rotate(const QQuaternion& quaternion) { // Algorithm from: // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54 @@ -1148,7 +1245,6 @@ QMatrix4x4& QMatrix4x4::rotate(const QQuaternion& quaternion) flagBits = flags | Rotation; else flagBits = Rotation; - return *this; } #endif @@ -1159,17 +1255,16 @@ QMatrix4x4& QMatrix4x4::rotate(const QQuaternion& quaternion) Multiplies this matrix by another that applies an orthographic projection for a window with boundaries specified by \a rect. The near and far clipping planes will be -1 and 1 respectively. - Returns this matrix. \sa frustum(), perspective() */ -QMatrix4x4& QMatrix4x4::ortho(const QRect& rect) +void QMatrix4x4::ortho(const QRect& rect) { // Note: rect.right() and rect.bottom() subtract 1 in QRect, // which gives the location of a pixel within the rectangle, // instead of the extent of the rectangle. We want the extent. // QRectF expresses the extent properly. - return ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f); + ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f); } /*! @@ -1178,28 +1273,27 @@ QMatrix4x4& QMatrix4x4::ortho(const QRect& rect) Multiplies this matrix by another that applies an orthographic projection for a window with boundaries specified by \a rect. The near and far clipping planes will be -1 and 1 respectively. - Returns this matrix. \sa frustum(), perspective() */ -QMatrix4x4& QMatrix4x4::ortho(const QRectF& rect) +void QMatrix4x4::ortho(const QRectF& rect) { - return ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f); + ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f); } /*! Multiplies this matrix by another that applies an orthographic projection for a window with lower-left corner (\a left, \a bottom), upper-right corner (\a right, \a top), and the specified \a nearPlane - and \a farPlane clipping planes. Returns this matrix. + and \a farPlane clipping planes. \sa frustum(), perspective() */ -QMatrix4x4& QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane) +void QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane) { // Bail out if the projection volume is zero-sized. if (left == right || bottom == top || nearPlane == farPlane) - return *this; + return; // Construct the projection. qreal width = right - left; @@ -1218,7 +1312,7 @@ QMatrix4x4& QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, (2.0f / width, 2.0f / invheight, -1.0f)); - return *this; + return; } #endif QMatrix4x4 m(1); @@ -1241,22 +1335,22 @@ QMatrix4x4& QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, // Apply the projection. *this *= m; - return *this; + return; } /*! Multiplies this matrix by another that applies a perspective frustum projection for a window with lower-left corner (\a left, \a bottom), upper-right corner (\a right, \a top), and the specified \a nearPlane - and \a farPlane clipping planes. Returns this matrix. + and \a farPlane clipping planes. \sa ortho(), perspective() */ -QMatrix4x4& QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane) +void QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane) { // Bail out if the projection volume is zero-sized. if (left == right || bottom == top || nearPlane == farPlane) - return *this; + return; // Construct the projection. QMatrix4x4 m(1); @@ -1282,7 +1376,6 @@ QMatrix4x4& QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top // Apply the projection. *this *= m; - return *this; } /*! @@ -1290,22 +1383,21 @@ QMatrix4x4& QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top projection. The field of view will be \a angle degrees within a window with a given \a aspect ratio. The projection will have the specified \a nearPlane and \a farPlane clipping planes. - Returns this matrix. \sa ortho(), frustum() */ -QMatrix4x4& QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane) +void QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane) { // Bail out if the projection volume is zero-sized. if (nearPlane == farPlane || aspect == 0.0f) - return *this; + return; // Construct the projection. QMatrix4x4 m(1); qreal radians = (angle / 2.0f) * M_PI / 180.0f; qreal sine = qSin(radians); if (sine == 0.0f) - return *this; + return; qreal cotan = qCos(radians) / sine; qreal clip = farPlane - nearPlane; m.m[0][0] = cotan / aspect; @@ -1327,7 +1419,6 @@ QMatrix4x4& QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, // Apply the projection. *this *= m; - return *this; } #ifndef QT_NO_VECTOR3D @@ -1337,9 +1428,8 @@ QMatrix4x4& QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, transformation. The \a center value indicates the center of the view that the \a eye is looking at. The \a up value indicates which direction should be considered up with respect to the \a eye. - Returns this matrix. */ -QMatrix4x4& QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up) +void QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up) { QVector3D forward = (center - eye).normalized(); QVector3D side = QVector3D::crossProduct(forward, up).normalized(); @@ -1365,7 +1455,7 @@ QMatrix4x4& QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, co m.m[3][3] = 1.0f; *this *= m; - return translate(-eye); + translate(-eye); } #endif @@ -1374,11 +1464,11 @@ QMatrix4x4& QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, co Flips between right-handed and left-handed coordinate systems by multiplying the y and z co-ordinates by -1. This is normally used to create a left-handed orthographic view without scaling - the viewport as ortho() does. Returns this matrix. + the viewport as ortho() does. \sa ortho() */ -QMatrix4x4& QMatrix4x4::flipCoordinates() +void QMatrix4x4::flipCoordinates() { if (flagBits == Scale || flagBits == (Scale | Translation)) { m[1][1] = -m[1][1]; @@ -1402,14 +1492,13 @@ QMatrix4x4& QMatrix4x4::flipCoordinates() m[2][3] = -m[2][3]; flagBits = General; } - return *this; } /*! - Retrieves the 16 items in this matrix and writes them to \a values + Retrieves the 16 items in this matrix and copies them to \a values in row-major order. */ -void QMatrix4x4::toValueArray(qreal *values) const +void QMatrix4x4::copyDataTo(qreal *values) const { for (int row = 0; row < 4; ++row) for (int col = 0; col < 4; ++col) @@ -1430,15 +1519,31 @@ QMatrix QMatrix4x4::toAffine() const m[3][0], m[3][1]); } -static const qreal inv_dist_to_plane = 1. / 1024.; +/*! + Returns the conventional Qt 2D transformation matrix that + corresponds to this matrix. + + The returned QTransform is formed by simply dropping the + third row and third column of the QMatrix4x4. This is suitable + for implementing orthographic projections where the z co-ordinate + should be dropped rather than projected. + + \sa toAffine() +*/ +QTransform QMatrix4x4::toTransform() const +{ + return QTransform(m[0][0], m[0][1], m[0][3], + m[1][0], m[1][1], m[1][3], + m[3][0], m[3][1], m[3][3]); +} /*! Returns the conventional Qt 2D transformation matrix that corresponds to this matrix. If \a distanceToPlane is non-zero, it indicates a projection - factor to use to adjust for the z co-ordinate. The default - value of 1024 corresponds to the projection factor used + factor to use to adjust for the z co-ordinate. The value of + 1024 corresponds to the projection factor used by QTransform::rotate() for the x and y axes. If \a distanceToPlane is zero, then the returned QTransform @@ -1617,7 +1722,7 @@ QRectF QMatrix4x4::mapRect(const QRectF& rect) const Returns a pointer to the raw data of this matrix. - \sa constData(), inferSpecialType() + \sa constData(), optimize() */ /*! @@ -1666,94 +1771,8 @@ QMatrix4x4 QMatrix4x4::orthonormalInverse() const return result; } -#ifndef QT_NO_VECTOR3D -/*! - Decomposes the current rotation matrix into an \a axis of rotation plus - an \a angle. The result can be used to construct an equivalent rotation - matrix using glRotate(). It is assumed that the homogenous coordinate - is 1.0. The returned vector is guaranteed to be normalized. - - \code - qreal angle; - QVector3D axis; - - matrix.extractAxisAngle(angle, axis); - glRotate(angle, axis[0], axis[1], axis[2]); - \endcode - - \sa rotate() -*/ -void QMatrix4x4::extractAxisRotation(qreal &angle, QVector3D &axis) const -{ - // Orientation is dependent on the upper 3x3 matrix; subtract the - // homogeneous scaling element from the trace of the 4x4 matrix - qreal tr = m[0][0] + m[1][1] + m[2][2]; - qreal cosa = qreal(0.5f * (tr - 1.0f)); - angle = acos(cosa) * 180.0f / M_PI; - - // Any axis will work if r is zero (means no rotation) - if (qFuzzyIsNull(angle)) { - axis.setX(1.0f); - axis.setY(0.0f); - axis.setZ(0.0f); - return; - } - - if (angle < 180.0f) { - axis.setX(m[1][2] - m[2][1]); - axis.setY(m[2][0] - m[0][2]); - axis.setZ(m[0][1] - m[1][0]); - axis.normalize(); - return; - } - - // rads == PI - qreal tmp; - - // r00 is maximum - if ((m[0][0] >= m[2][2]) && (m[0][0] >= m[1][1])) { - axis.setX(0.5f * qSqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f)); - tmp = 0.5f / axis.x(); - axis.setY(m[1][0] * tmp); - axis.setZ(m[2][0] * tmp); - } - - // r11 is maximum - if ((m[1][1] >= m[2][2]) && (m[1][1] >= m[0][0])) { - axis.setY(0.5f * qSqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f)); - tmp = 0.5f / axis.y(); - axis.setX(tmp * m[1][0]); - axis.setZ(tmp * m[2][1]); - } - - // r22 is maximum - if ((m[2][2] >= m[1][1]) && (m[2][2] >= m[0][0])) { - axis.setZ(0.5f * qSqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f)); - tmp = 0.5f / axis.z(); - axis.setX(m[2][0]*tmp); - axis.setY(m[2][1]*tmp); - } -} - -/*! - If this is an orthonormal transformation matrix (e.g. only rotations and - translations have been applied to the matrix, no scaling, or shearing) - then the world translational component can be obtained by calling this function. - - This is most useful for camera matrices, where the negation of this vector - is effectively the camera world coordinates. -*/ -QVector3D QMatrix4x4::extractTranslation() const -{ - return QVector3D - (m[0][0] * m[3][0] + m[0][1] * m[3][1] + m[0][2] * m[3][2], - m[1][0] * m[3][0] + m[1][1] * m[3][1] + m[1][2] * m[3][2], - m[2][0] * m[3][0] + m[2][1] * m[3][1] + m[2][2] * m[3][2]); -} -#endif - /*! - Infers the special type of this matrix from its current elements. + Optimize the usage of this matrix from its current elements. Some operations such as translate(), scale(), and rotate() can be performed more efficiently if the matrix being modified is already @@ -1766,13 +1785,13 @@ QVector3D QMatrix4x4::extractTranslation() const the special type and will revert to the safest but least efficient operations thereafter. - By calling inferSpecialType() after directly modifying the matrix, + By calling optimize() after directly modifying the matrix, the programmer can force QMatrix4x4 to recover the special type if the elements appear to conform to one of the known optimized types. \sa operator()(), data(), translate() */ -void QMatrix4x4::inferSpecialType() +void QMatrix4x4::optimize() { // If the last element is not 1, then it can never be special. if (m[3][3] != 1.0f) { @@ -1889,7 +1908,7 @@ QDataStream &operator>>(QDataStream &stream, QMatrix4x4 &matrix) matrix(row, col) = qreal(x); } } - matrix.inferSpecialType(); + matrix.optimize(); return stream; } diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index b32e00a..4193bdc 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -63,7 +63,7 @@ class QVariant; class Q_GUI_EXPORT QMatrix4x4 { public: - inline QMatrix4x4() { setIdentity(); } + inline QMatrix4x4() { setToIdentity(); } explicit QMatrix4x4(const qreal *values); inline QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14, qreal m21, qreal m22, qreal m23, qreal m24, @@ -87,7 +87,7 @@ public: inline void setRow(int index, const QVector4D& value); inline bool isIdentity() const; - inline void setIdentity(); + inline void setToIdentity(); inline void fill(qreal value); @@ -127,39 +127,35 @@ public: friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2); #ifndef QT_NO_VECTOR3D - QMatrix4x4& scale(const QVector3D& vector); - QMatrix4x4& translate(const QVector3D& vector); - QMatrix4x4& rotate(qreal angle, const QVector3D& vector); + void scale(const QVector3D& vector); + void translate(const QVector3D& vector); + void rotate(qreal angle, const QVector3D& vector); #endif - QMatrix4x4& scale(qreal x, qreal y); - QMatrix4x4& scale(qreal x, qreal y, qreal z); - QMatrix4x4& scale(qreal factor); - QMatrix4x4& translate(qreal x, qreal y); - QMatrix4x4& translate(qreal x, qreal y, qreal z); - QMatrix4x4& rotate(qreal angle, qreal x, qreal y, qreal z = 0.0f); + void scale(qreal x, qreal y); + void scale(qreal x, qreal y, qreal z); + void scale(qreal factor); + void translate(qreal x, qreal y); + void translate(qreal x, qreal y, qreal z); + void rotate(qreal angle, qreal x, qreal y, qreal z = 0.0f); #ifndef QT_NO_QUATERNION - QMatrix4x4& rotate(const QQuaternion& quaternion); + void rotate(const QQuaternion& quaternion); #endif + void ortho(const QRect& rect); + void ortho(const QRectF& rect); + void ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane); + void frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane); + void perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane); #ifndef QT_NO_VECTOR3D - void extractAxisRotation(qreal &angle, QVector3D &axis) const; - QVector3D extractTranslation() const; + void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up); #endif + void flipCoordinates(); - QMatrix4x4& ortho(const QRect& rect); - QMatrix4x4& ortho(const QRectF& rect); - QMatrix4x4& ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane); - QMatrix4x4& frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane); - QMatrix4x4& perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane); -#ifndef QT_NO_VECTOR3D - QMatrix4x4& lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up); -#endif - QMatrix4x4& flipCoordinates(); - - void toValueArray(qreal *values) const; + void copyDataTo(qreal *values) const; QMatrix toAffine() const; - QTransform toTransform(qreal distanceToPlane = 1024.0f) const; + QTransform toTransform() const; + QTransform toTransform(qreal distanceToPlane) const; QPoint map(const QPoint& point) const; QPointF map(const QPointF& point) const; @@ -182,7 +178,7 @@ public: inline const qreal *data() const { return m[0]; } inline const qreal *constData() const { return m[0]; } - void inferSpecialType(); + void optimize(); operator QVariant() const; @@ -206,6 +202,10 @@ private: QMatrix4x4(int) { flagBits = General; } QMatrix4x4 orthonormalInverse() const; + + void projectedRotate(qreal angle, qreal x, qreal y, qreal z); + + friend class QGraphicsRotation; }; inline QMatrix4x4::QMatrix4x4 @@ -325,7 +325,7 @@ inline bool QMatrix4x4::isIdentity() const return (m[3][3] == 1.0f); } -inline void QMatrix4x4::setIdentity() +inline void QMatrix4x4::setToIdentity() { m[0][0] = 1.0f; m[0][1] = 0.0f; diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index d5ec054..626cb3c 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -288,7 +288,7 @@ void QQuaternion::normalize() in 3D space. The following code: \code - QVector3D result = q.rotateVector(vector); + QVector3D result = q.rotatedVector(vector); \endcode is equivalent to the following: @@ -297,7 +297,7 @@ void QQuaternion::normalize() QVector3D result = (q * QQuaternion(0, vector) * q.conjugate()).vector(); \endcode */ -QVector3D QQuaternion::rotateVector(const QVector3D& vector) const +QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const { return (*this * QQuaternion(0, vector) * conjugate()).vector(); } diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index 7480a5c..5b2454f 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -95,7 +95,7 @@ public: QQuaternion conjugate() const; - QVector3D rotateVector(const QVector3D& vector) const; + QVector3D rotatedVector(const QVector3D& vector) const; QQuaternion &operator+=(const QQuaternion &quaternion); QQuaternion &operator-=(const QQuaternion &quaternion); diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 7c07df8..f36470a 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -56,6 +56,7 @@ #include <private/qwindowsurface_raster_p.h> #include <private/qapplication_p.h> #include <private/qpaintengine_raster_p.h> +#include <private/qgraphicseffect_p.h> #include "qgraphicssystem_p.h" @@ -497,18 +498,6 @@ static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately) if (!widget) return; -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) - if (QApplicationPrivate::inSizeMove && widget->internalWinId() && !updateImmediately - && !widget->testAttribute(Qt::WA_DontShowOnScreen)) { - // Tell Windows to send us a paint event if we're in WM_SIZE/WM_MOVE; posted events - // are blocked until the mouse button is released. See task 146849. - const QRegion rgn(qt_dirtyRegion(widget)); - InvalidateRgn(widget->internalWinId(), rgn.handle(), false); - qt_widget_private(widget)->dirty = QRegion(); - return; - } -#endif - if (updateImmediately) { QEvent event(QEvent::UpdateRequest); QApplication::sendEvent(widget, &event); @@ -540,6 +529,8 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up Q_ASSERT(widget->window() == tlw); Q_ASSERT(!rgn.isEmpty()); + widget->d_func()->invalidateGraphicsEffectsRecursively(); + if (widget->d_func()->paintOnScreen()) { if (widget->d_func()->dirty.isEmpty()) { widget->d_func()->dirty = rgn; @@ -615,6 +606,8 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd Q_ASSERT(widget->window() == tlw); Q_ASSERT(!rect.isEmpty()); + widget->d_func()->invalidateGraphicsEffectsRecursively(); + if (widget->d_func()->paintOnScreen()) { if (widget->d_func()->dirty.isEmpty()) { widget->d_func()->dirty = QRegion(rect); @@ -886,7 +879,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) const QRect parentRect(rect & clipR); bool accelerateMove = accelEnv && isOpaque -#ifndef QT_NO_GRAPHICSCVIEW +#ifndef QT_NO_GRAPHICSVIEW // No accelerate move for proxy widgets. && !tlw->d_func()->extra->proxyWidget #endif @@ -1184,7 +1177,7 @@ void QWidgetBackingStore::sync() : wd->dirty); toClean += widgetDirty; -#ifndef QT_NO_GRAPHICSCVIEW +#ifndef QT_NO_GRAPHICSVIEW if (tlw->d_func()->extra->proxyWidget) { resetWidget(w); continue; diff --git a/src/gui/painting/qbackingstore_p.h b/src/gui/painting/qbackingstore_p.h index 94d756e..3288dae 100644 --- a/src/gui/painting/qbackingstore_p.h +++ b/src/gui/painting/qbackingstore_p.h @@ -97,6 +97,12 @@ public: ); } + // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). + void markDirty(const QRegion &rgn, QWidget *widget, bool updateImmediately = false, + bool invalidateBuffer = false); + void markDirty(const QRect &rect, QWidget *widget, bool updateImmediately = false, + bool invalidateBuffer = false); + private: QWidget *tlw; QRegion dirtyOnScreen; // needsFlush @@ -126,11 +132,6 @@ private: QRegion dirtyRegion(QWidget *widget = 0) const; QRegion staticContents(QWidget *widget = 0, const QRect &withinClipRect = QRect()) const; - // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). - void markDirty(const QRegion &rgn, QWidget *widget, bool updateImmediately = false, - bool invalidateBuffer = false); - void markDirty(const QRect &rect, QWidget *widget, bool updateImmediately = false, - bool invalidateBuffer = false); void markDirtyOnScreen(const QRegion &dirtyOnScreen, QWidget *widget, const QPoint &topLevelOffset); void removeDirtyWidget(QWidget *w); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 53edbb0..41602a1 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -7424,6 +7424,14 @@ QT_RECTFILL(qrgb444) QT_RECTFILL(qargb4444) #undef QT_RECTFILL +inline static void qt_rectfill_nonpremul_quint32(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + quint32 color) +{ + qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), + INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine()); +} + // Map table for destination image format. Contains function pointers // for blends of various types unto the destination @@ -7466,7 +7474,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = qt_bitmapblit_quint32, qt_alphamapblit_quint32, qt_alphargbblit_quint32, - qt_rectfill_quint32 + qt_rectfill_nonpremul_quint32 }, // Format_ARGB32_Premultiplied { diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index fd0e810..8d0b961 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1686,7 +1686,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) if (!s->penData.blend) return; - if (s->flags.fast_pen && path.shape() <= QVectorPath::NonCurvedShapeHint + if (s->flags.fast_pen && !path.isCurved() && s->lastPen.brush().isOpaque()) { int count = path.elementCount(); QPointF *points = (QPointF *) path.points(); @@ -1739,8 +1739,7 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); for (int i = 0; i < lineCount; ++i) { - if (path.shape() == QVectorPath::LinesHint) - dashOffset = s->lastPen.dashOffset(); + dashOffset = s->lastPen.dashOffset(); if (lines[i].p1() == lines[i].p2()) { if (s->lastPen.capStyle() != Qt::FlatCap) { QPointF p = lines[i].p1(); @@ -5120,6 +5119,9 @@ void QSpanData::adjustSpanMethods() #else unclipped_blend = qBlendTexture; #endif + if (!texture.imageData) + unclipped_blend = 0; + break; } // setup clipping diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index 59482c6..35b77f7 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -146,7 +146,7 @@ static inline int qpainterOpToXrender(QPainter::CompositionMode mode) // hack, so we don't have to make QRegion::clipRectangles() public or include // X11 headers in qregion.h -Q_AUTOTEST_EXPORT void *qt_getClipRects(const QRegion &r, int &num) +Q_GUI_EXPORT void *qt_getClipRects(const QRegion &r, int &num) { return r.clipRectangles(num); } diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 195be0a..9e21182 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -92,6 +92,24 @@ QRectF QVectorPath::controlPointRect() const return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2)); } + +QVectorPath::CacheEntry *QVectorPath::addCacheData(QPaintEngineEx *engine, void *data, + qvectorpath_cache_cleanup cleanup) { + Q_ASSERT(!lookupCacheData(engine)); + if ((m_hints & IsCachedHint) == 0) { + m_cache = 0; + m_hints |= IsCachedHint; + } + CacheEntry *e = new CacheEntry; + e->engine = engine; + e->data = data; + e->cleanup = cleanup; + e->next = m_cache; + m_cache = e; + return m_cache; +} + + const QVectorPath &qtVectorPathForPath(const QPainterPath &path) { Q_ASSERT(path.d_func()); @@ -414,7 +432,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) // Some engines might decide to optimize for the non-shape hint later on... uint flags = QVectorPath::WindingFill; if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; // ### Perspective Xforms are currently not supported... if (!pen.isCosmetic()) { @@ -442,7 +460,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) points[4], points[5]); points += 6; types += 3; - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; break; default: break; @@ -504,7 +522,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); points += 6; types += 3; - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; break; } default: @@ -736,7 +754,7 @@ void QPaintEngineEx::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yR x1 + xRadius, y1 }; - QVectorPath path(pts, 17, qpaintengineex_roundedrect_types); + QVectorPath path(pts, 17, qpaintengineex_roundedrect_types, QVectorPath::RoundedRectHint); draw(path); } @@ -827,7 +845,7 @@ void QPaintEngineEx::drawPoints(const QPointF *points, int pointCount) pts[++oset] = points[i].x() + 0.001; pts[++oset] = points[i].y(); } - QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint); + QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint); stroke(path, pen); pointCount -= 16; points += 16; @@ -858,7 +876,7 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount) pts[++oset] = points[i].x() + 0.001; pts[++oset] = points[i].y(); } - QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::NonCurvedShapeHint); + QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint); stroke(path, pen); pointCount -= 16; points += 16; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 3ec9bd6..02d77f4 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -250,9 +250,9 @@ public: inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { switch (mode) { case QPaintEngine::ConvexMode: return ConvexPolygonHint | ImplicitClose; - case QPaintEngine::OddEvenMode: return NonCurvedShapeHint | OddEvenFill | ImplicitClose; - case QPaintEngine::WindingMode: return NonCurvedShapeHint | WindingFill | ImplicitClose; - case QPaintEngine::PolylineMode: return NonCurvedShapeHint; + case QPaintEngine::OddEvenMode: return PolygonHint | OddEvenFill | ImplicitClose; + case QPaintEngine::WindingMode: return PolygonHint | WindingFill | ImplicitClose; + case QPaintEngine::PolylineMode: return PolygonHint; default: return 0; } } diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index cddad7d..09a4563 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2275,8 +2275,9 @@ void QPainter::setBrushOrigin(const QPointF &p) /*! Sets the composition mode to the given \a mode. - \warning You can only set the composition mode for QPainter - objects that operates on a QImage. + \warning Only a QPainter operating on a QImage fully supports all + composition modes. The RasterOp modes are supported for X11 as + described in compositionMode(). \sa compositionMode() */ @@ -5163,7 +5164,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm) Q_D(QPainter); - if (!d->engine) + if (!d->engine || pm.isNull()) return; #ifndef QT_NO_DEBUG @@ -7603,7 +7604,7 @@ start_lengthVariant: l.setPosition(QPointF(0., height)); height += l.height(); width = qMax(width, l.naturalTextWidth()); - if (!brect && height >= r.height()) + if (!dontclip && !brect && height >= r.height()) break; } textLayout.endLayout(); diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 69e189c..8133793 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -688,6 +688,8 @@ void QPainterPath::lineTo(const QPointF &p) return; Element elm = { p.x(), p.y(), LineToElement }; d->elements.append(elm); + + d->convex = d->elements.size() == 3 || (d->elements.size() == 4 && d->isClosed()); } /*! @@ -960,6 +962,8 @@ void QPainterPath::addRect(const QRectF &r) ensureData(); detach(); + bool first = d_func()->elements.size() < 2; + d_func()->elements.reserve(d_func()->elements.size() + 5); moveTo(r.x(), r.y()); @@ -970,6 +974,7 @@ void QPainterPath::addRect(const QRectF &r) d_func()->elements << l1 << l2 << l3 << l4; d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -1039,6 +1044,7 @@ void QPainterPath::addEllipse(const QRectF &boundingRect) detach(); Q_D(QPainterPath); + bool first = d_func()->elements.size() < 2; d->elements.reserve(d->elements.size() + 13); QPointF pts[12]; @@ -1051,6 +1057,8 @@ void QPainterPath::addEllipse(const QRectF &boundingRect) cubicTo(pts[6], pts[7], pts[8]); // 180 -> 90 cubicTo(pts[9], pts[10], pts[11]); // 90 - >0 d_func()->require_moveTo = true; + + d_func()->convex = first; } /*! @@ -3027,14 +3035,17 @@ void QPainterPath::addRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadi ensureData(); detach(); - arcMoveTo(x, y, rxx2, ryy2, 90); - arcTo(x, y, rxx2, ryy2, 90, 90); - arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90); - arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 3*90, 90); - arcTo(x+w-rxx2, y, rxx2, ryy2, 0, 90); + bool first = d_func()->elements.size() < 2; + + arcMoveTo(x, y, rxx2, ryy2, 180); + arcTo(x, y, rxx2, ryy2, 180, -90); + arcTo(x+w-rxx2, y, rxx2, ryy2, 90, -90); + arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 0, -90); + arcTo(x, y+h-ryy2, rxx2, ryy2, 270, -90); closeSubpath(); d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -3081,14 +3092,17 @@ void QPainterPath::addRoundRect(const QRectF &r, int xRnd, int yRnd) ensureData(); detach(); - arcMoveTo(x, y, rxx2, ryy2, 90); - arcTo(x, y, rxx2, ryy2, 90, 90); - arcTo(x, y+h-ryy2, rxx2, ryy2, 2*90, 90); - arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 3*90, 90); - arcTo(x+w-rxx2, y, rxx2, ryy2, 0, 90); + bool first = d_func()->elements.size() < 2; + + arcMoveTo(x, y, rxx2, ryy2, 180); + arcTo(x, y, rxx2, ryy2, 180, -90); + arcTo(x+w-rxx2, y, rxx2, ryy2, 90, -90); + arcTo(x+w-rxx2, y+h-ryy2, rxx2, ryy2, 0, -90); + arcTo(x, y+h-ryy2, rxx2, ryy2, 270, -90); closeSubpath(); d_func()->require_moveTo = true; + d_func()->convex = first; } /*! @@ -3269,6 +3283,7 @@ void QPainterPath::setDirty(bool dirty) d_func()->dirtyControlBounds = dirty; delete d_func()->pathConverter; d_func()->pathConverter = 0; + d_func()->convex = false; } void QPainterPath::computeBoundingRect() const diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index 54c182d..54b9392 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -81,8 +81,8 @@ class QVectorPathConverter; class QVectorPathConverter { public: - QVectorPathConverter(const QVector<QPainterPath::Element> &path, uint fillRule) - : pathData(path, fillRule), + QVectorPathConverter(const QVector<QPainterPath::Element> &path, uint fillRule, bool convex) + : pathData(path, fillRule, convex), path(pathData.points.data(), path.size(), pathData.elements.data(), pathData.flags) {} @@ -91,7 +91,7 @@ public: } struct QVectorPathData { - QVectorPathData(const QVector<QPainterPath::Element> &path, uint fillRule) + QVectorPathData(const QVector<QPainterPath::Element> &path, uint fillRule, bool convex) : elements(path.size()), points(path.size() * 2), flags(0) @@ -103,7 +103,7 @@ public: points[ptsPos++] = e.x; points[ptsPos++] = e.y; if (e.type == QPainterPath::CurveToElement) - flags |= QVectorPath::CurvedShapeHint; + flags |= QVectorPath::CurvedShapeMask; } if (fillRule == Qt::WindingFill) @@ -111,6 +111,8 @@ public: else flags |= QVectorPath::OddEvenFill; + if (!convex) + flags |= QVectorPath::NonConvexShapeMask; } QVarLengthArray<QPainterPath::ElementType> elements; QVarLengthArray<qreal> points; @@ -128,19 +130,24 @@ class QPainterPathData : public QPainterPathPrivate { public: QPainterPathData() : - cStart(0), fillRule(Qt::OddEvenFill), - dirtyBounds(false), dirtyControlBounds(false), + cStart(0), + fillRule(Qt::OddEvenFill), + dirtyBounds(false), + dirtyControlBounds(false), pathConverter(0) { ref = 1; require_moveTo = false; + convex = false; } QPainterPathData(const QPainterPathData &other) : QPainterPathPrivate(), cStart(other.cStart), fillRule(other.fillRule), - dirtyBounds(other.dirtyBounds), bounds(other.bounds), - dirtyControlBounds(other.dirtyControlBounds), + bounds(other.bounds), controlBounds(other.controlBounds), + dirtyBounds(other.dirtyBounds), + dirtyControlBounds(other.dirtyControlBounds), + convex(other.convex), pathConverter(0) { ref = 1; @@ -158,20 +165,21 @@ public: const QVectorPath &vectorPath() { if (!pathConverter) - pathConverter = new QVectorPathConverter(elements, fillRule); + pathConverter = new QVectorPathConverter(elements, fillRule, convex); return pathConverter->path; } int cStart; Qt::FillRule fillRule; - bool require_moveTo; - - bool dirtyBounds; QRectF bounds; - bool dirtyControlBounds; QRectF controlBounds; + uint require_moveTo : 1; + uint dirtyBounds : 1; + uint dirtyControlBounds : 1; + uint convex : 1; + QVectorPathConverter *pathConverter; }; diff --git a/src/gui/painting/qprinterinfo_unix.cpp b/src/gui/painting/qprinterinfo_unix.cpp index 7e2946a..6684ff7 100644 --- a/src/gui/painting/qprinterinfo_unix.cpp +++ b/src/gui/painting/qprinterinfo_unix.cpp @@ -421,6 +421,7 @@ int qt_pd_foreach(int /*status */, char * /*key */, int /*keyLen */, int qt_retrieveNisPrinters(QList<QPrinterDescription> *printers) { +#ifndef QT_NO_LIBRARY typedef int (*WildCast)(int, char *, int, char *, int, char *); char printersConfByname[] = "printers.conf.byname"; char *domain; @@ -444,6 +445,7 @@ int qt_retrieveNisPrinters(QList<QPrinterDescription> *printers) if (!err) return Success; } +#endif //QT_NO_LIBRARY return Unavail; } diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index c57b3c1..228a6b1 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -452,6 +452,17 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine #endif if (join == FlatJoin) { + QLineF prevLine(qt_fixed_to_real(m_back2X), qt_fixed_to_real(m_back2Y), + qt_fixed_to_real(m_back1X), qt_fixed_to_real(m_back1Y)); + QPointF isect; + QLineF::IntersectType type = prevLine.intersect(nextLine, &isect); + QLineF shortCut(prevLine.p2(), nextLine.p1()); + qreal angle = shortCut.angleTo(prevLine); + if (type == QLineF::BoundedIntersection || (angle > 90 && !qFuzzyCompare(angle, (qreal)90))) { + emitLineTo(focal_x, focal_y); + emitLineTo(qt_real_to_fixed(nextLine.x1()), qt_real_to_fixed(nextLine.y1())); + return; + } emitLineTo(qt_real_to_fixed(nextLine.x1()), qt_real_to_fixed(nextLine.y1())); @@ -468,8 +479,8 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine // If we are on the inside, do the short cut... QLineF shortCut(prevLine.p2(), nextLine.p1()); qreal angle = shortCut.angleTo(prevLine); - if (type == QLineF::BoundedIntersection || (angle > 90 && !qFuzzyCompare(angle, (qreal)90))) { + emitLineTo(focal_x, focal_y); emitLineTo(qt_real_to_fixed(nextLine.x1()), qt_real_to_fixed(nextLine.y1())); return; } @@ -509,8 +520,9 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine qfixed offset = m_strokeWidth / 2; QLineF shortCut(prevLine.p2(), nextLine.p1()); - qreal angle = prevLine.angle(shortCut); + qreal angle = shortCut.angleTo(prevLine); if (type == QLineF::BoundedIntersection || (angle > 90 && !qFuzzyCompare(angle, (qreal)90))) { + emitLineTo(focal_x, focal_y); emitLineTo(qt_real_to_fixed(nextLine.x1()), qt_real_to_fixed(nextLine.y1())); return; } @@ -581,6 +593,13 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine qt_real_to_fixed(l1.x1()), qt_real_to_fixed(l1.y1())); } else if (join == SvgMiterJoin) { + QLineF shortCut(prevLine.p2(), nextLine.p1()); + qreal angle = shortCut.angleTo(prevLine); + if (type == QLineF::BoundedIntersection || (angle > 90 && !qFuzzyCompare(angle, (qreal)90))) { + emitLineTo(focal_x, focal_y); + emitLineTo(qt_real_to_fixed(nextLine.x1()), qt_real_to_fixed(nextLine.y1())); + return; + } QLineF miterLine(QPointF(qt_fixed_to_real(focal_x), qt_fixed_to_real(focal_y)), isect); if (miterLine.length() > qt_fixed_to_real(m_strokeWidth * m_miterLimit) / 2) { diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h index d023131..ec27970 100644 --- a/src/gui/painting/qvectorpath_p.h +++ b/src/gui/painting/qvectorpath_p.h @@ -66,8 +66,9 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) +class QPaintEngineEx; -#define QVECTORPATH_NO_CACHE +typedef void (*qvectorpath_cache_cleanup)(void *data); struct QRealRect { qreal x1, y1, x2, y2; @@ -77,19 +78,27 @@ class Q_GUI_EXPORT QVectorPath { public: enum Hint { - // Basic shapes... - LinesHint = 0x0001, // Just plain lines... - RectangleHint = 0x0002, - ConvexPolygonHint = 0x0003, // Convex polygon... - NonISectPolygonHint = 0x0004, // concave polygon, but not intersecting.. - NonCurvedShapeHint = 0x0005, // Generic polygon, possibly self-intersecting... - CurvedShapeHint = 0x0006, // Generic vector path.. - EllipseHint = 0x0007, - ShapeHintMask = 0x000f, + // Shape hints, in 0x000000ff, access using shape() + AreaShapeMask = 0x0001, // shape covers an area + NonConvexShapeMask = 0x0002, // shape is not convex + CurvedShapeMask = 0x0004, // shape contains curves... + LinesShapeMask = 0x0008, + RectangleShapeMask = 0x0010, + ShapeMask = 0x001f, + + // Shape hints merged into basic shapes.. + LinesHint = LinesShapeMask, + RectangleHint = AreaShapeMask | RectangleShapeMask, + EllipseHint = AreaShapeMask | CurvedShapeMask, + ConvexPolygonHint = AreaShapeMask, + PolygonHint = AreaShapeMask | NonConvexShapeMask, + RoundedRectHint = AreaShapeMask | CurvedShapeMask, + ArbitraryShapeHint = AreaShapeMask | NonConvexShapeMask | CurvedShapeMask, // Other hints - CacheHint = 0x0100, - ControlPointRect = 0x0200, // Set if the control point rect has been calculated... + IsCachedHint = 0x0100, // Set if the cache hint is set + ShouldUseCacheHint = 0x0200, // Set if the path should be cached when possible.. + ControlPointRect = 0x0400, // Set if the control point rect has been calculated... // Shape rendering specifiers... OddEvenFill = 0x1000, @@ -101,22 +110,21 @@ public: QVectorPath(const qreal *points, int count, const QPainterPath::ElementType *elements = 0, - uint hints = CurvedShapeHint) + uint hints = ArbitraryShapeHint) : m_elements(elements), m_points(points), m_count(count), m_hints(hints) -#ifndef QVECTORPATH_NO_CACHE - , m_cache(0) -#endif { } QRectF controlPointRect() const; - inline Hint shape() const { return (Hint) (m_hints & ShapeHintMask); } + inline Hint shape() const { return (Hint) (m_hints & ShapeMask); } + inline bool isConvex() const { return (m_hints & NonConvexShapeMask) == 0; } + inline bool isCurved() const { return m_hints & CurvedShapeMask; } - inline bool hasCacheHint() const { return m_hints & CacheHint; } + inline bool isCacheable() const { return m_hints & ShouldUseCacheHint; } inline bool hasImplicitClose() const { return m_hints & ImplicitClose; } inline bool hasWindingFill() const { return m_hints & WindingFill; } @@ -131,24 +139,30 @@ public: static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode); -private: - Q_DISABLE_COPY(QVectorPath) - -#ifndef QVECTORPATH_NO_CACHE struct CacheEntry { - void *engine; - int id; - void *extra; + QPaintEngineEx *engine; + void *data; + qvectorpath_cache_cleanup cleanup; CacheEntry *next; }; - void addCacheData(CacheEntry *d) { - d->next = m_cache; - m_cache = d; + CacheEntry *addCacheData(QPaintEngineEx *engine, void *data, qvectorpath_cache_cleanup cleanup); + inline CacheEntry *lookupCacheData(QPaintEngineEx *engine) const { + Q_ASSERT(m_hints & IsCachedHint); + CacheEntry *e = m_cache; + while (e) { + if (e->engine == engine) + return e; + e = e->next; + } + return 0; } + +private: + Q_DISABLE_COPY(QVectorPath) + CacheEntry *m_cache; -#endif const QPainterPath::ElementType *m_elements; const qreal *m_points; diff --git a/src/gui/painting/qwindowsurface_qws.cpp b/src/gui/painting/qwindowsurface_qws.cpp index 4f489c4..fa0c80e 100644 --- a/src/gui/painting/qwindowsurface_qws.cpp +++ b/src/gui/painting/qwindowsurface_qws.cpp @@ -668,9 +668,11 @@ void QWSWindowSurface::flush(QWidget *widget, const QRegion ®ion, if (!win) return; +#ifndef QT_NO_GRAPHICSVIEW QWExtra *extra = win->d_func()->extra; if (extra && extra->proxyWidget) return; +#endif //QT_NO_GRAPHICSVIEW Q_UNUSED(offset); diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 3a118bd..d412040 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -215,6 +215,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi XCopyArea(X11->display, d_ptr->image->xshmpm, widget->handle(), d_ptr->gc, br.x(), br.y(), br.width(), br.height(), wbr.x(), wbr.y()); XSync(X11->display, False); + } else if (d_ptr->image->xshmimg) { + const QImage &src = d->image->image; + br = br.intersected(src.rect()); + XShmPutImage(X11->display, widget->handle(), d_ptr->gc, d_ptr->image->xshmimg, + br.x(), br.y(), wbr.x(), wbr.y(), br.width(), br.height(), False); + XSync(X11->display, False); } else #endif { diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp index 46c4c42..77e019c 100644 --- a/src/gui/painting/qwindowsurface_x11.cpp +++ b/src/gui/painting/qwindowsurface_x11.cpp @@ -94,6 +94,8 @@ QPaintDevice *QX11WindowSurface::paintDevice() void QX11WindowSurface::beginPaint(const QRegion &rgn) { #ifndef QT_NO_XRENDER + Q_ASSERT(!d_ptr->device.isNull()); + if (d_ptr->translucentBackground) { if (d_ptr->device.depth() != 32) static_cast<QX11PixmapData *>(d_ptr->device.data_ptr().data())->convertToARGB32(); @@ -157,8 +159,8 @@ void QX11WindowSurface::setGeometry(const QRect &rect) QPixmap::x11SetDefaultScreen(d_ptr->widget->x11Info().screen()); QX11PixmapData *oldData = static_cast<QX11PixmapData *>(d_ptr->device.pixmapData()); - Q_ASSERT(oldData); - if (!(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) { + + if (oldData && !(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) { // Copy the content of the old pixmap into the new one. QX11PixmapData *newData = new QX11PixmapData(QPixmapData::PixmapType); newData->resize(size.width(), size.height()); diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index 4ad78f9..4c4c994 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -163,7 +163,7 @@ void QS60MainAppUi::HandleResourceChangeL(TInt type) /*! * \brief Handles raw window server events. * - * The event type and information is passed in \a event, while the receiving control is passed in + * The event type and information is passed in \a wsEvent, while the receiving control is passed in * \a destination. * * If you override this function, you should call the base class implementation if you do not diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp index 445a253..bf10e3d 100644 --- a/src/gui/statemachine/qbasickeyeventtransition.cpp +++ b/src/gui/statemachine/qbasickeyeventtransition.cpp @@ -68,14 +68,14 @@ public: QEvent::Type eventType; int key; - Qt::KeyboardModifiers modifiersMask; + Qt::KeyboardModifiers modifierMask; }; QBasicKeyEventTransitionPrivate::QBasicKeyEventTransitionPrivate() { eventType = QEvent::None; key = 0; - modifiersMask = Qt::NoModifier; + modifierMask = Qt::NoModifier; } QBasicKeyEventTransitionPrivate *QBasicKeyEventTransitionPrivate::get(QBasicKeyEventTransition *q) @@ -106,17 +106,17 @@ QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key, /*! Constructs a new event transition for events of the given \a type for the - given \a key, with the given \a modifiersMask and \a sourceState. + given \a key, with the given \a modifierMask and \a sourceState. */ QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key, - Qt::KeyboardModifiers modifiersMask, + Qt::KeyboardModifiers modifierMask, QState *sourceState) : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState) { Q_D(QBasicKeyEventTransition); d->eventType = type; d->key = key; - d->modifiersMask = modifiersMask; + d->modifierMask = modifierMask; } /*! @@ -163,23 +163,23 @@ void QBasicKeyEventTransition::setKey(int key) } /*! - Returns the keyboard modifiers mask that this key event transition checks + Returns the keyboard modifier mask that this key event transition checks for. */ -Qt::KeyboardModifiers QBasicKeyEventTransition::modifiersMask() const +Qt::KeyboardModifiers QBasicKeyEventTransition::modifierMask() const { Q_D(const QBasicKeyEventTransition); - return d->modifiersMask; + return d->modifierMask; } /*! - Sets the keyboard modifiers mask that this key event transition will check + Sets the keyboard modifier mask that this key event transition will check for. */ -void QBasicKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +void QBasicKeyEventTransition::setModifierMask(Qt::KeyboardModifiers modifierMask) { Q_D(QBasicKeyEventTransition); - d->modifiersMask = modifiersMask; + d->modifierMask = modifierMask; } /*! @@ -191,7 +191,7 @@ bool QBasicKeyEventTransition::eventTest(QEvent *event) if (event->type() == d->eventType) { QKeyEvent *ke = static_cast<QKeyEvent*>(event); return (ke->key() == d->key) - && ((ke->modifiers() & d->modifiersMask) == d->modifiersMask); + && ((ke->modifiers() & d->modifierMask) == d->modifierMask); } return false; } diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h index 3c2ec7d..87d3dc7 100644 --- a/src/gui/statemachine/qbasickeyeventtransition_p.h +++ b/src/gui/statemachine/qbasickeyeventtransition_p.h @@ -69,7 +69,7 @@ public: QBasicKeyEventTransition(QState *sourceState = 0); QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = 0); QBasicKeyEventTransition(QEvent::Type type, int key, - Qt::KeyboardModifiers modifiersMask, + Qt::KeyboardModifiers modifierMask, QState *sourceState = 0); ~QBasicKeyEventTransition(); @@ -79,8 +79,8 @@ public: int key() const; void setKey(int key); - Qt::KeyboardModifiers modifiersMask() const; - void setModifiersMask(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifierMask() const; + void setModifierMask(Qt::KeyboardModifiers modifiers); protected: bool eventTest(QEvent *event); diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp index 694c319..fe0dea9 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition.cpp +++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp @@ -69,7 +69,7 @@ public: QEvent::Type eventType; Qt::MouseButton button; - Qt::KeyboardModifiers modifiersMask; + Qt::KeyboardModifiers modifierMask; QPainterPath path; }; @@ -149,38 +149,38 @@ void QBasicMouseEventTransition::setButton(Qt::MouseButton button) } /*! - Returns the keyboard modifiers mask that this mouse event transition checks + Returns the keyboard modifier mask that this mouse event transition checks for. */ -Qt::KeyboardModifiers QBasicMouseEventTransition::modifiersMask() const +Qt::KeyboardModifiers QBasicMouseEventTransition::modifierMask() const { Q_D(const QBasicMouseEventTransition); - return d->modifiersMask; + return d->modifierMask; } /*! - Sets the keyboard modifiers mask that this mouse event transition will check + Sets the keyboard modifier mask that this mouse event transition will check for. */ -void QBasicMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +void QBasicMouseEventTransition::setModifierMask(Qt::KeyboardModifiers modifierMask) { Q_D(QBasicMouseEventTransition); - d->modifiersMask = modifiersMask; + d->modifierMask = modifierMask; } /*! - Returns the path for this mouse event transition. + Returns the hit test path for this mouse event transition. */ -QPainterPath QBasicMouseEventTransition::path() const +QPainterPath QBasicMouseEventTransition::hitTestPath() const { Q_D(const QBasicMouseEventTransition); return d->path; } /*! - Sets the path for this mouse event transition. + Sets the hit test path for this mouse event transition. */ -void QBasicMouseEventTransition::setPath(const QPainterPath &path) +void QBasicMouseEventTransition::setHitTestPath(const QPainterPath &path) { Q_D(QBasicMouseEventTransition); d->path = path; @@ -195,7 +195,7 @@ bool QBasicMouseEventTransition::eventTest(QEvent *event) if (event->type() == d->eventType) { QMouseEvent *me = static_cast<QMouseEvent*>(event); return (me->button() == d->button) - && ((me->modifiers() & d->modifiersMask) == d->modifiersMask) + && ((me->modifiers() & d->modifierMask) == d->modifierMask) && (d->path.isEmpty() || d->path.contains(me->pos())); } return false; diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h index 512e0f8..6754c55 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition_p.h +++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h @@ -79,11 +79,11 @@ public: Qt::MouseButton button() const; void setButton(Qt::MouseButton button); - Qt::KeyboardModifiers modifiersMask() const; - void setModifiersMask(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifierMask() const; + void setModifierMask(Qt::KeyboardModifiers modifiers); - QPainterPath path() const; - void setPath(const QPainterPath &path); + QPainterPath hitTestPath() const; + void setHitTestPath(const QPainterPath &path); protected: bool eventTest(QEvent *event); diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index dee3168..a15e671 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -69,9 +69,9 @@ QT_BEGIN_NAMESPACE */ /*! - \property QKeyEventTransition::modifiersMask + \property QKeyEventTransition::modifierMask - \brief the keyboard modifiers mask that this key event transition checks for + \brief the keyboard modifier mask that this key event transition checks for */ class QKeyEventTransitionPrivate : public QEventTransitionPrivate @@ -133,23 +133,23 @@ void QKeyEventTransition::setKey(int key) } /*! - Returns the keyboard modifiers mask that this key event transition checks + Returns the keyboard modifier mask that this key event transition checks for. */ -Qt::KeyboardModifiers QKeyEventTransition::modifiersMask() const +Qt::KeyboardModifiers QKeyEventTransition::modifierMask() const { Q_D(const QKeyEventTransition); - return d->transition->modifiersMask(); + return d->transition->modifierMask(); } /*! - Sets the keyboard \a modifiers mask that this key event transition will - check for. + Sets the keyboard modifier mask that this key event transition will + check for to \a modifierMask. */ -void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +void QKeyEventTransition::setModifierMask(Qt::KeyboardModifiers modifierMask) { Q_D(QKeyEventTransition); - d->transition->setModifiersMask(modifiersMask); + d->transition->setModifierMask(modifierMask); } /*! diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h index 8df8138..ab1c155 100644 --- a/src/gui/statemachine/qkeyeventtransition.h +++ b/src/gui/statemachine/qkeyeventtransition.h @@ -57,7 +57,7 @@ class Q_GUI_EXPORT QKeyEventTransition : public QEventTransition { Q_OBJECT Q_PROPERTY(int key READ key WRITE setKey) - Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask) + Q_PROPERTY(Qt::KeyboardModifiers modifierMask READ modifierMask WRITE setModifierMask) public: QKeyEventTransition(QState *sourceState = 0); QKeyEventTransition(QObject *object, QEvent::Type type, int key, @@ -67,8 +67,8 @@ public: int key() const; void setKey(int key); - Qt::KeyboardModifiers modifiersMask() const; - void setModifiersMask(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifierMask() const; + void setModifierMask(Qt::KeyboardModifiers modifiers); protected: void onTransition(QEvent *event); diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index 86cacf7..f5c0cb1 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -70,9 +70,9 @@ QT_BEGIN_NAMESPACE */ /*! - \property QMouseEventTransition::modifiersMask + \property QMouseEventTransition::modifierMask - \brief the keyboard modifiers mask that this mouse event transition checks for + \brief the keyboard modifier mask that this mouse event transition checks for */ class QMouseEventTransitionPrivate : public QEventTransitionPrivate @@ -139,45 +139,45 @@ void QMouseEventTransition::setButton(Qt::MouseButton button) } /*! - Returns the keyboard modifiers mask that this mouse event transition checks + Returns the keyboard modifier mask that this mouse event transition checks for. */ -Qt::KeyboardModifiers QMouseEventTransition::modifiersMask() const +Qt::KeyboardModifiers QMouseEventTransition::modifierMask() const { Q_D(const QMouseEventTransition); - return d->transition->modifiersMask(); + return d->transition->modifierMask(); } /*! - Sets the keyboard \a modifiers mask that this mouse event transition will - check for. + Sets the keyboard modifier mask that this mouse event transition will + check for to \a modifierMask. */ -void QMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +void QMouseEventTransition::setModifierMask(Qt::KeyboardModifiers modifierMask) { Q_D(QMouseEventTransition); - d->transition->setModifiersMask(modifiersMask); + d->transition->setModifierMask(modifierMask); } /*! - Returns the path for this mouse event transition. + Returns the hit test path for this mouse event transition. */ -QPainterPath QMouseEventTransition::path() const +QPainterPath QMouseEventTransition::hitTestPath() const { Q_D(const QMouseEventTransition); - return d->transition->path(); + return d->transition->hitTestPath(); } /*! - Sets the \a path for this mouse event transition. + Sets the hit test path for this mouse event transition to \a path. If a valid path has been set, the transition will only trigger if the mouse event position (QMouseEvent::pos()) is inside the path. \sa QPainterPath::contains() */ -void QMouseEventTransition::setPath(const QPainterPath &path) +void QMouseEventTransition::setHitTestPath(const QPainterPath &path) { Q_D(QMouseEventTransition); - d->transition->setPath(path); + d->transition->setHitTestPath(path); } /*! diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h index 4e324ec..e7f6a45 100644 --- a/src/gui/statemachine/qmouseeventtransition.h +++ b/src/gui/statemachine/qmouseeventtransition.h @@ -58,7 +58,7 @@ class Q_GUI_EXPORT QMouseEventTransition : public QEventTransition { Q_OBJECT Q_PROPERTY(Qt::MouseButton button READ button WRITE setButton) - Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask) + Q_PROPERTY(Qt::KeyboardModifiers modifierMask READ modifierMask WRITE setModifierMask) public: QMouseEventTransition(QState *sourceState = 0); QMouseEventTransition(QObject *object, QEvent::Type type, @@ -68,11 +68,11 @@ public: Qt::MouseButton button() const; void setButton(Qt::MouseButton button); - Qt::KeyboardModifiers modifiersMask() const; - void setModifiersMask(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifierMask() const; + void setModifierMask(Qt::KeyboardModifiers modifiers); - QPainterPath path() const; - void setPath(const QPainterPath &path); + QPainterPath hitTestPath() const; + void setHitTestPath(const QPainterPath &path); protected: void onTransition(QEvent *event); diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp deleted file mode 100644 index 6ec5796..0000000 --- a/src/gui/styles/gtksymbols.cpp +++ /dev/null @@ -1,1005 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** 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.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "gtksymbols_p.h" - -// This file is responsible for resolving all GTK functions we use -// dynamically. This is done to avoid link-time dependancy on GTK -// as well as crashes occurring due to usage of the GTK_QT engines -// -// Additionally we create a map of common GTK widgets that we can pass -// to the GTK theme engine as many engines resort to querying the -// actual widget pointers for details that are not covered by the -// state flags - -#include <QtCore/qglobal.h> -#if !defined(QT_NO_STYLE_GTK) - -#include <QtCore/QEvent> -#include <QtCore/QFile> -#include <QtCore/QStringList> -#include <QtCore/QTextStream> -#include <QtCore/QHash> -#include <QtCore/QUrl> - -#include <private/qapplication_p.h> -#include <private/qiconloader_p.h> - -#include <QtGui/QMenu> -#include <QtGui/QStyle> -#include <QtGui/QApplication> -#include <QtGui/QPixmapCache> -#include <QtGui/QStatusBar> -#include <QtGui/QMenuBar> -#include <QtGui/QToolBar> -#include <QtGui/QToolButton> -#include <QtGui/QX11Info> - -#include <X11/Xlib.h> - -QT_BEGIN_NAMESPACE - -static bool displayDepth = -1; -Q_GLOBAL_STATIC(QGtkStyleUpdateScheduler, styleScheduler) - -typedef QHash<QString, GtkWidget*> WidgetMap; -Q_GLOBAL_STATIC(WidgetMap, gtkWidgetMap) - -Ptr_gtk_container_forall QGtk::gtk_container_forall = 0; -Ptr_gtk_init QGtk::gtk_init = 0; -Ptr_gtk_style_attach QGtk::gtk_style_attach = 0; -Ptr_gtk_window_new QGtk::gtk_window_new = 0; -Ptr_gtk_widget_destroy QGtk::gtk_widget_destroy = 0; -Ptr_gtk_widget_realize QGtk::gtk_widget_realize = 0; -Ptr_gtk_widget_set_default_direction QGtk::gtk_widget_set_default_direction = 0; -Ptr_gtk_widget_modify_color QGtk::gtk_widget_modify_fg = 0; -Ptr_gtk_widget_modify_color QGtk::gtk_widget_modify_bg = 0; -Ptr_gtk_arrow_new QGtk::gtk_arrow_new = 0; -Ptr_gtk_menu_item_new QGtk::gtk_menu_item_new = 0; -Ptr_gtk_check_menu_item_new QGtk::gtk_check_menu_item_new = 0; -Ptr_gtk_menu_bar_new QGtk::gtk_menu_bar_new = 0; -Ptr_gtk_menu_new QGtk::gtk_menu_new = 0; -Ptr_gtk_button_new QGtk::gtk_button_new = 0; -Ptr_gtk_hbutton_box_new QGtk::gtk_hbutton_box_new = 0; -Ptr_gtk_check_button_new QGtk::gtk_check_button_new = 0; -Ptr_gtk_radio_button_new QGtk::gtk_radio_button_new = 0; -Ptr_gtk_spin_button_new QGtk::gtk_spin_button_new = 0; -Ptr_gtk_frame_new QGtk::gtk_frame_new = 0; -Ptr_gtk_expander_new QGtk::gtk_expander_new = 0; -Ptr_gtk_statusbar_new QGtk::gtk_statusbar_new = 0; -Ptr_gtk_entry_new QGtk::gtk_entry_new = 0; -Ptr_gtk_hscale_new QGtk::gtk_hscale_new = 0; -Ptr_gtk_vscale_new QGtk::gtk_vscale_new = 0; -Ptr_gtk_hscrollbar_new QGtk::gtk_hscrollbar_new = 0; -Ptr_gtk_vscrollbar_new QGtk::gtk_vscrollbar_new = 0; -Ptr_gtk_scrolled_window_new QGtk::gtk_scrolled_window_new = 0; -Ptr_gtk_notebook_new QGtk::gtk_notebook_new = 0; -Ptr_gtk_toolbar_new QGtk::gtk_toolbar_new = 0; -Ptr_gtk_toolbar_insert QGtk::gtk_toolbar_insert = 0; -Ptr_gtk_separator_tool_item_new QGtk::gtk_separator_tool_item_new = 0; -Ptr_gtk_tree_view_new QGtk::gtk_tree_view_new = 0; -Ptr_gtk_combo_box_new QGtk::gtk_combo_box_new = 0; -Ptr_gtk_combo_box_entry_new QGtk::gtk_combo_box_entry_new = 0; -Ptr_gtk_progress_bar_new QGtk::gtk_progress_bar_new = 0; -Ptr_gtk_container_add QGtk::gtk_container_add = 0; -Ptr_gtk_menu_shell_append QGtk::gtk_menu_shell_append = 0; -Ptr_gtk_progress_set_adjustment QGtk::gtk_progress_set_adjustment = 0; -Ptr_gtk_range_set_adjustment QGtk::gtk_range_set_adjustment = 0; -Ptr_gtk_range_set_inverted QGtk::gtk_range_set_inverted = 0; -Ptr_gtk_icon_factory_lookup_default QGtk::gtk_icon_factory_lookup_default = 0; -Ptr_gtk_icon_theme_get_default QGtk::gtk_icon_theme_get_default = 0; -Ptr_gtk_widget_style_get QGtk::gtk_widget_style_get = 0; -Ptr_gtk_icon_set_render_icon QGtk::gtk_icon_set_render_icon = 0; -Ptr_gtk_fixed_new QGtk::gtk_fixed_new = 0; -Ptr_gtk_tree_view_column_new QGtk::gtk_tree_view_column_new = 0; -Ptr_gtk_tree_view_get_column QGtk::gtk_tree_view_get_column = 0; -Ptr_gtk_tree_view_append_column QGtk::gtk_tree_view_append_column = 0; -Ptr_gtk_paint_check QGtk::gtk_paint_check = 0; -Ptr_gtk_paint_box QGtk::gtk_paint_box = 0; -Ptr_gtk_paint_box_gap QGtk::gtk_paint_box_gap = 0; -Ptr_gtk_paint_flat_box QGtk::gtk_paint_flat_box = 0; -Ptr_gtk_paint_option QGtk::gtk_paint_option = 0; -Ptr_gtk_paint_extension QGtk::gtk_paint_extension = 0; -Ptr_gtk_paint_slider QGtk::gtk_paint_slider = 0; -Ptr_gtk_paint_shadow QGtk::gtk_paint_shadow = 0; -Ptr_gtk_paint_resize_grip QGtk::gtk_paint_resize_grip = 0; -Ptr_gtk_paint_focus QGtk::gtk_paint_focus = 0; -Ptr_gtk_paint_arrow QGtk::gtk_paint_arrow = 0; -Ptr_gtk_paint_handle QGtk::gtk_paint_handle = 0; -Ptr_gtk_paint_expander QGtk::gtk_paint_expander = 0; -Ptr_gtk_adjustment_new QGtk::gtk_adjustment_new = 0; -Ptr_gtk_paint_hline QGtk::gtk_paint_hline = 0; -Ptr_gtk_paint_vline QGtk::gtk_paint_vline = 0; -Ptr_gtk_menu_item_set_submenu QGtk::gtk_menu_item_set_submenu = 0; -Ptr_gtk_settings_get_default QGtk::gtk_settings_get_default = 0; -Ptr_gtk_separator_menu_item_new QGtk::gtk_separator_menu_item_new = 0; -Ptr_gtk_widget_size_allocate QGtk::gtk_widget_size_allocate = 0; -Ptr_gtk_widget_set_direction QGtk::gtk_widget_set_direction = 0; -Ptr_gtk_widget_path QGtk::gtk_widget_path = 0; -Ptr_gtk_container_get_type QGtk::gtk_container_get_type = 0; -Ptr_gtk_window_get_type QGtk::gtk_window_get_type = 0; -Ptr_gtk_widget_get_type QGtk::gtk_widget_get_type = 0; -Ptr_gtk_rc_get_style_by_paths QGtk::gtk_rc_get_style_by_paths = 0; -Ptr_gtk_check_version QGtk::gtk_check_version = 0; - -Ptr_pango_font_description_get_size QGtk::pango_font_description_get_size = 0; -Ptr_pango_font_description_get_weight QGtk::pango_font_description_get_weight = 0; -Ptr_pango_font_description_get_family QGtk::pango_font_description_get_family = 0; -Ptr_pango_font_description_get_style QGtk::pango_font_description_get_style = 0; - -Ptr_gtk_file_filter_new QGtk::gtk_file_filter_new = 0; -Ptr_gtk_file_filter_set_name QGtk::gtk_file_filter_set_name = 0; -Ptr_gtk_file_filter_add_pattern QGtk::gtk_file_filter_add_pattern = 0; -Ptr_gtk_file_chooser_add_filter QGtk::gtk_file_chooser_add_filter = 0; -Ptr_gtk_file_chooser_set_filter QGtk::gtk_file_chooser_set_filter = 0; -Ptr_gtk_file_chooser_get_filter QGtk::gtk_file_chooser_get_filter = 0; -Ptr_gtk_file_chooser_dialog_new QGtk::gtk_file_chooser_dialog_new = 0; -Ptr_gtk_file_chooser_set_current_folder QGtk::gtk_file_chooser_set_current_folder = 0; -Ptr_gtk_file_chooser_get_filename QGtk::gtk_file_chooser_get_filename = 0; -Ptr_gtk_file_chooser_get_filenames QGtk::gtk_file_chooser_get_filenames = 0; -Ptr_gtk_file_chooser_set_current_name QGtk::gtk_file_chooser_set_current_name = 0; -Ptr_gtk_dialog_run QGtk::gtk_dialog_run = 0; -Ptr_gtk_file_chooser_set_filename QGtk::gtk_file_chooser_set_filename = 0; - -Ptr_gdk_pixbuf_get_pixels QGtk::gdk_pixbuf_get_pixels = 0; -Ptr_gdk_pixbuf_get_width QGtk::gdk_pixbuf_get_width = 0; -Ptr_gdk_pixbuf_get_height QGtk::gdk_pixbuf_get_height = 0; -Ptr_gdk_pixmap_new QGtk::gdk_pixmap_new = 0; -Ptr_gdk_pixbuf_new QGtk::gdk_pixbuf_new = 0; -Ptr_gdk_pixbuf_get_from_drawable QGtk::gdk_pixbuf_get_from_drawable = 0; -Ptr_gdk_draw_rectangle QGtk::gdk_draw_rectangle = 0; -Ptr_gdk_pixbuf_unref QGtk::gdk_pixbuf_unref = 0; -Ptr_gdk_drawable_unref QGtk::gdk_drawable_unref = 0; -Ptr_gdk_drawable_get_depth QGtk::gdk_drawable_get_depth = 0; -Ptr_gdk_color_free QGtk::gdk_color_free = 0; -Ptr_gdk_x11_window_set_user_time QGtk::gdk_x11_window_set_user_time = 0; -Ptr_gdk_x11_drawable_get_xid QGtk::gdk_x11_drawable_get_xid = 0; -Ptr_gdk_x11_drawable_get_xdisplay QGtk::gdk_x11_drawable_get_xdisplay = 0; - -Ptr_gconf_client_get_default QGtk::gconf_client_get_default = 0; -Ptr_gconf_client_get_string QGtk::gconf_client_get_string = 0; -Ptr_gconf_client_get_bool QGtk::gconf_client_get_bool = 0; - -Ptr_gnome_icon_lookup_sync QGtk::gnome_icon_lookup_sync = 0; -Ptr_gnome_vfs_init QGtk::gnome_vfs_init = 0; - -static QString classPath(GtkWidget *widget) -{ - char* class_path; - QGtk::gtk_widget_path (widget, NULL, &class_path, NULL); - QString path = QLS(class_path); - g_free(class_path); - - // Remove the prefixes - path.remove(QLS("GtkWindow.")); - path.remove(QLS("GtkFixed.")); - return path; -} - -static void resolveGtk() -{ - // enforce the "0" suffix, so we'll open libgtk-x11-2.0.so.0 - QLibrary libgtk(QLS("gtk-x11-2.0"), 0, 0); - QGtk::gtk_init = (Ptr_gtk_init)libgtk.resolve("gtk_init"); - QGtk::gtk_window_new = (Ptr_gtk_window_new)libgtk.resolve("gtk_window_new"); - QGtk::gtk_style_attach = (Ptr_gtk_style_attach)libgtk.resolve("gtk_style_attach"); - QGtk::gtk_widget_destroy = (Ptr_gtk_widget_destroy)libgtk.resolve("gtk_widget_destroy"); - QGtk::gtk_widget_realize = (Ptr_gtk_widget_realize)libgtk.resolve("gtk_widget_realize"); - - QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); - QGtk::gtk_file_filter_new = (Ptr_gtk_file_filter_new)libgtk.resolve("gtk_file_filter_new"); - QGtk::gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)libgtk.resolve("gtk_file_filter_set_name"); - QGtk::gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)libgtk.resolve("gtk_file_filter_add_pattern"); - QGtk::gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)libgtk.resolve("gtk_file_chooser_add_filter"); - QGtk::gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)libgtk.resolve("gtk_file_chooser_set_filter"); - QGtk::gtk_file_chooser_get_filter = (Ptr_gtk_file_chooser_get_filter)libgtk.resolve("gtk_file_chooser_get_filter"); - QGtk::gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)libgtk.resolve("gtk_file_chooser_dialog_new"); - QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); - QGtk::gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)libgtk.resolve("gtk_file_chooser_get_filename"); - QGtk::gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)libgtk.resolve("gtk_file_chooser_get_filenames"); - QGtk::gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)libgtk.resolve("gtk_file_chooser_set_current_name"); - QGtk::gtk_dialog_run = (Ptr_gtk_dialog_run)libgtk.resolve("gtk_dialog_run"); - QGtk::gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)libgtk.resolve("gtk_file_chooser_set_filename"); - - QGtk::gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)libgtk.resolve("gdk_pixbuf_get_pixels"); - QGtk::gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)libgtk.resolve("gdk_pixbuf_get_width"); - QGtk::gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)libgtk.resolve("gdk_pixbuf_get_height"); - QGtk::gdk_pixmap_new = (Ptr_gdk_pixmap_new)libgtk.resolve("gdk_pixmap_new"); - QGtk::gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)libgtk.resolve("gdk_pixbuf_new"); - QGtk::gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)libgtk.resolve("gdk_pixbuf_get_from_drawable"); - QGtk::gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)libgtk.resolve("gdk_draw_rectangle"); - QGtk::gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)libgtk.resolve("gdk_pixbuf_unref"); - QGtk::gdk_drawable_unref = (Ptr_gdk_drawable_unref)libgtk.resolve("gdk_drawable_unref"); - QGtk::gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)libgtk.resolve("gdk_drawable_get_depth"); - QGtk::gdk_color_free = (Ptr_gdk_color_free)libgtk.resolve("gdk_color_free"); - QGtk::gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)libgtk.resolve("gdk_x11_window_set_user_time"); - QGtk::gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)libgtk.resolve("gdk_x11_drawable_get_xid"); - QGtk::gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)libgtk.resolve("gdk_x11_drawable_get_xdisplay"); - - QGtk::gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)libgtk.resolve("gtk_widget_set_default_direction"); - QGtk::gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_fg"); - QGtk::gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_bg"); - QGtk::gtk_arrow_new = (Ptr_gtk_arrow_new)libgtk.resolve("gtk_arrow_new"); - QGtk::gtk_menu_item_new = (Ptr_gtk_menu_item_new)libgtk.resolve("gtk_menu_item_new"); - QGtk::gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)libgtk.resolve("gtk_check_menu_item_new"); - QGtk::gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)libgtk.resolve("gtk_menu_bar_new"); - QGtk::gtk_menu_new = (Ptr_gtk_menu_new)libgtk.resolve("gtk_menu_new"); - QGtk::gtk_toolbar_new = (Ptr_gtk_toolbar_new)libgtk.resolve("gtk_toolbar_new"); - QGtk::gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)libgtk.resolve("gtk_separator_tool_item_new"); - QGtk::gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)libgtk.resolve("gtk_toolbar_insert"); - QGtk::gtk_button_new = (Ptr_gtk_button_new)libgtk.resolve("gtk_button_new"); - QGtk::gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)libgtk.resolve("gtk_hbutton_box_new"); - QGtk::gtk_check_button_new = (Ptr_gtk_check_button_new)libgtk.resolve("gtk_check_button_new"); - QGtk::gtk_radio_button_new = (Ptr_gtk_radio_button_new)libgtk.resolve("gtk_radio_button_new"); - QGtk::gtk_notebook_new = (Ptr_gtk_notebook_new)libgtk.resolve("gtk_notebook_new"); - QGtk::gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)libgtk.resolve("gtk_progress_bar_new"); - QGtk::gtk_spin_button_new = (Ptr_gtk_spin_button_new)libgtk.resolve("gtk_spin_button_new"); - QGtk::gtk_hscale_new = (Ptr_gtk_hscale_new)libgtk.resolve("gtk_hscale_new"); - QGtk::gtk_vscale_new = (Ptr_gtk_vscale_new)libgtk.resolve("gtk_vscale_new"); - QGtk::gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)libgtk.resolve("gtk_hscrollbar_new"); - QGtk::gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)libgtk.resolve("gtk_vscrollbar_new"); - QGtk::gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)libgtk.resolve("gtk_scrolled_window_new"); - QGtk::gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)libgtk.resolve("gtk_menu_shell_append"); - QGtk::gtk_entry_new = (Ptr_gtk_entry_new)libgtk.resolve("gtk_entry_new"); - QGtk::gtk_tree_view_new = (Ptr_gtk_tree_view_new)libgtk.resolve("gtk_tree_view_new"); - QGtk::gtk_combo_box_new = (Ptr_gtk_combo_box_new)libgtk.resolve("gtk_combo_box_new"); - QGtk::gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)libgtk.resolve("gtk_progress_set_adjustment"); - QGtk::gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)libgtk.resolve("gtk_range_set_adjustment"); - QGtk::gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)libgtk.resolve("gtk_range_set_inverted"); - QGtk::gtk_container_add = (Ptr_gtk_container_add)libgtk.resolve("gtk_container_add"); - QGtk::gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)libgtk.resolve("gtk_icon_factory_lookup_default"); - QGtk::gtk_icon_theme_get_default = (Ptr_gtk_icon_theme_get_default)libgtk.resolve("gtk_icon_theme_get_default"); - QGtk::gtk_widget_style_get = (Ptr_gtk_widget_style_get)libgtk.resolve("gtk_widget_style_get"); - QGtk::gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)libgtk.resolve("gtk_icon_set_render_icon"); - QGtk::gtk_fixed_new = (Ptr_gtk_fixed_new)libgtk.resolve("gtk_fixed_new"); - QGtk::gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)libgtk.resolve("gtk_tree_view_column_new"); - QGtk::gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )libgtk.resolve("gtk_tree_view_append_column"); - QGtk::gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )libgtk.resolve("gtk_tree_view_get_column"); - QGtk::gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check"); - QGtk::gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box"); - QGtk::gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)libgtk.resolve("gtk_paint_flat_box"); - QGtk::gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check"); - QGtk::gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box"); - QGtk::gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)libgtk.resolve("gtk_paint_resize_grip"); - QGtk::gtk_paint_focus = (Ptr_gtk_paint_focus)libgtk.resolve("gtk_paint_focus"); - QGtk::gtk_paint_shadow = (Ptr_gtk_paint_shadow)libgtk.resolve("gtk_paint_shadow"); - QGtk::gtk_paint_slider = (Ptr_gtk_paint_slider)libgtk.resolve("gtk_paint_slider"); - QGtk::gtk_paint_expander = (Ptr_gtk_paint_expander)libgtk.resolve("gtk_paint_expander"); - QGtk::gtk_paint_handle = (Ptr_gtk_paint_handle)libgtk.resolve("gtk_paint_handle"); - QGtk::gtk_paint_option = (Ptr_gtk_paint_option)libgtk.resolve("gtk_paint_option"); - QGtk::gtk_paint_arrow = (Ptr_gtk_paint_arrow)libgtk.resolve("gtk_paint_arrow"); - QGtk::gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)libgtk.resolve("gtk_paint_box_gap"); - QGtk::gtk_paint_extension = (Ptr_gtk_paint_extension)libgtk.resolve("gtk_paint_extension"); - QGtk::gtk_paint_hline = (Ptr_gtk_paint_hline)libgtk.resolve("gtk_paint_hline"); - QGtk::gtk_paint_vline = (Ptr_gtk_paint_vline)libgtk.resolve("gtk_paint_vline"); - QGtk::gtk_adjustment_new = (Ptr_gtk_adjustment_new)libgtk.resolve("gtk_adjustment_new"); - QGtk::gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)libgtk.resolve("gtk_menu_item_set_submenu"); - QGtk::gtk_settings_get_default = (Ptr_gtk_settings_get_default)libgtk.resolve("gtk_settings_get_default"); - QGtk::gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)libgtk.resolve("gtk_separator_menu_item_new"); - QGtk::gtk_frame_new = (Ptr_gtk_frame_new)libgtk.resolve("gtk_frame_new"); - QGtk::gtk_expander_new = (Ptr_gtk_expander_new)libgtk.resolve("gtk_expander_new"); - QGtk::gtk_statusbar_new = (Ptr_gtk_statusbar_new)libgtk.resolve("gtk_statusbar_new"); - QGtk::gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)libgtk.resolve("gtk_combo_box_entry_new"); - QGtk::gtk_container_forall = (Ptr_gtk_container_forall)libgtk.resolve("gtk_container_forall"); - QGtk::gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)libgtk.resolve("gtk_widget_size_allocate"); - QGtk::gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)libgtk.resolve("gtk_widget_set_direction"); - QGtk::gtk_widget_path =(Ptr_gtk_widget_path)libgtk.resolve("gtk_widget_path"); - QGtk::gtk_container_get_type =(Ptr_gtk_container_get_type)libgtk.resolve("gtk_container_get_type"); - QGtk::gtk_window_get_type =(Ptr_gtk_window_get_type)libgtk.resolve("gtk_window_get_type"); - QGtk::gtk_widget_get_type =(Ptr_gtk_widget_get_type)libgtk.resolve("gtk_widget_get_type"); - QGtk::gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)libgtk.resolve("gtk_rc_get_style_by_paths"); - QGtk::gtk_check_version =(Ptr_gtk_check_version)libgtk.resolve("gtk_check_version"); - QGtk::pango_font_description_get_size = (Ptr_pango_font_description_get_size)libgtk.resolve("pango_font_description_get_size"); - QGtk::pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)libgtk.resolve("pango_font_description_get_weight"); - QGtk::pango_font_description_get_family = (Ptr_pango_font_description_get_family)libgtk.resolve("pango_font_description_get_family"); - QGtk::pango_font_description_get_style = (Ptr_pango_font_description_get_style)libgtk.resolve("pango_font_description_get_style"); - - QGtk::gnome_icon_lookup_sync = (Ptr_gnome_icon_lookup_sync)QLibrary::resolve( QLS("gnomeui-2"), 0, "gnome_icon_lookup_sync"); - QGtk::gnome_vfs_init= (Ptr_gnome_vfs_init)QLibrary::resolve( QLS("gnomevfs-2"), 0, "gnome_vfs_init"); -} - -void QGtk::cleanup_gtk_widgets() -{ - if (gtkWidgetMap()->contains(QLS("GtkWindow"))) // Gtk will destroy all children - QGtk::gtk_widget_destroy(gtkWidgetMap()->value(QLS("GtkWindow"))); -} - -static bool resolveGConf() -{ - if (!QGtk::gconf_client_get_default) { - QGtk::gconf_client_get_default = (Ptr_gconf_client_get_default)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_default"); - QGtk::gconf_client_get_string = (Ptr_gconf_client_get_string)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_string"); - QGtk::gconf_client_get_bool = (Ptr_gconf_client_get_bool)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_bool"); - } - return (QGtk::gconf_client_get_default !=0); -} - -typedef int (*x11ErrorHandler)(Display*, XErrorEvent*); - -QString QGtk::getGConfString(const QString &value, const QString &fallback) -{ - QString retVal = fallback; - if (resolveGConf()) { - g_type_init(); - GConfClient* client = QGtk::gconf_client_get_default(); - GError *err = 0; - char *str = QGtk::gconf_client_get_string(client, qPrintable(value), &err); - if (!err) { - retVal = QString::fromUtf8(str); - g_free(str); - } - g_object_unref(client); - if (err) - g_error_free (err); - } - return retVal; -} - -bool QGtk::getGConfBool(const QString &key, bool fallback) -{ - bool retVal = fallback; - if (resolveGConf()) { - g_type_init(); - GConfClient* client = QGtk::gconf_client_get_default(); - GError *err = 0; - bool result = QGtk::gconf_client_get_bool(client, qPrintable(key), &err); - g_object_unref(client); - if (!err) - retVal = result; - else - g_error_free (err); - } - return retVal; -} - -static QString getThemeName() -{ - QString themeName; - // We try to parse the gtkrc file first - // primarily to avoid resolving Gtk functions if - // the KDE 3 "Qt" style is currently in use - QString rcPaths = QString::fromLocal8Bit(qgetenv("GTK2_RC_FILES")); - if (!rcPaths.isEmpty()) { - QStringList paths = rcPaths.split(QLS(":")); - foreach (const QString &rcPath, paths) { - if (!rcPath.isEmpty()) { - QFile rcFile(rcPath); - if (rcFile.exists() && rcFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QTextStream in(&rcFile); - while(!in.atEnd()) { - QString line = in.readLine(); - if (line.contains(QLS("gtk-theme-name"))) { - line = line.right(line.length() - line.indexOf(QLatin1Char('=')) - 1); - line.remove(QLatin1Char('\"')); - line = line.trimmed(); - themeName = line; - break; - } - } - } - } - if (!themeName.isEmpty()) - break; - } - } - - // Fall back to gconf - if (themeName.isEmpty() && resolveGConf()) - themeName = QGtk::getGConfString(QLS("/desktop/gnome/interface/gtk_theme")); - - return themeName; -} - -static void init_gtk_window() -{ - static QString themeName; - if (!gtkWidgetMap()->contains(QLS("GtkWindow")) && themeName.isEmpty()) { - themeName = getThemeName(); - - if (themeName.isEmpty()) { - qWarning("QGtkStyle was unable to detect the current GTK+ theme."); - return; - } else if (themeName == QLS("Qt") || themeName == QLS("Qt4")) { - // Due to namespace conflicts with Qt3 and obvious recursion with Qt4, - // we cannot support the GTK_Qt Gtk engine - qWarning("QGtkStyle cannot be used together with the GTK_Qt engine."); - return; - } - - resolveGtk(); - - if (QGtk::gtk_init) { - // Gtk will set the Qt error handler so we have to reset it afterwards - x11ErrorHandler qt_x_errhandler = XSetErrorHandler(0); - QGtk::gtk_init (NULL, NULL); - XSetErrorHandler(qt_x_errhandler); - - GtkWidget* gtkWindow = QGtk::gtk_window_new(GTK_WINDOW_POPUP); - QGtk::gtk_widget_realize(gtkWindow); - if (displayDepth == -1) - displayDepth = QGtk::gdk_drawable_get_depth(gtkWindow->window); - gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow); - } else { - qWarning("QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries."); - } - } -} - -static void setup_gtk_widget(GtkWidget* widget) -{ - if (Q_GTK_IS_WIDGET(widget)) { - static GtkWidget* protoLayout = 0; - if (!protoLayout) { - protoLayout = QGtk::gtk_fixed_new(); - QGtk::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value(QLS("GtkWindow"))), protoLayout); - } - Q_ASSERT(protoLayout); - - QGtk::gtk_container_add((GtkContainer*)(protoLayout), widget); - QGtk::gtk_widget_realize(widget); - } -} - -static void add_widget_to_map(GtkWidget *widget) -{ - if (Q_GTK_IS_WIDGET(widget)) { - QGtk::gtk_widget_realize(widget); - gtkWidgetMap()->insert(classPath(widget), widget); - } - } - -static void add_all_sub_widgets(GtkWidget *widget, gpointer v = 0) -{ - Q_UNUSED(v); - add_widget_to_map(widget); - if (GTK_CHECK_TYPE ((widget), Q_GTK_TYPE_CONTAINER)) - QGtk::gtk_container_forall((GtkContainer*)widget, add_all_sub_widgets, NULL); -} - -static void init_gtk_menu() -{ - // Create menubar - GtkWidget *gtkMenuBar = QGtk::gtk_menu_bar_new(); - setup_gtk_widget(gtkMenuBar); - - GtkWidget *gtkMenuBarItem = QGtk::gtk_menu_item_new(); - QGtk::gtk_menu_shell_append((GtkMenuShell*)(gtkMenuBar), gtkMenuBarItem); - QGtk::gtk_widget_realize(gtkMenuBarItem); - - // Create menu - GtkWidget *gtkMenu = QGtk::gtk_menu_new(); - QGtk::gtk_menu_item_set_submenu((GtkMenuItem*)(gtkMenuBarItem), gtkMenu); - QGtk::gtk_widget_realize(gtkMenu); - - GtkWidget *gtkMenuItem = QGtk::gtk_menu_item_new(); - QGtk::gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuItem); - QGtk::gtk_widget_realize(gtkMenuItem); - - GtkWidget *gtkCheckMenuItem = QGtk::gtk_check_menu_item_new(); - QGtk::gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkCheckMenuItem); - QGtk::gtk_widget_realize(gtkCheckMenuItem); - - GtkWidget *gtkMenuSeparator = QGtk::gtk_separator_menu_item_new(); - QGtk::gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuSeparator); - - add_all_sub_widgets(gtkMenuBar); - add_all_sub_widgets(gtkMenu); -} - -// Updates window/windowtext palette based on the indicated gtk widget -static QPalette gtkWidgetPalette(const QString >kWidgetName) -{ - GtkWidget *gtkWidget = QGtk::gtkWidget(gtkWidgetName); - Q_ASSERT(gtkWidget); - QPalette pal = QApplication::palette(); - GdkColor gdkBg = gtkWidget->style->bg[GTK_STATE_NORMAL]; - GdkColor gdkText = gtkWidget->style->fg[GTK_STATE_NORMAL]; - GdkColor gdkDisabledText = gtkWidget->style->fg[GTK_STATE_INSENSITIVE]; - QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); - QColor textColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); - QColor disabledTextColor(gdkDisabledText.red>>8, gdkDisabledText.green>>8, gdkDisabledText.blue>>8); - pal.setBrush(QPalette::Window, bgColor); - pal.setBrush(QPalette::Button, bgColor); - pal.setBrush(QPalette::All, QPalette::WindowText, textColor); - pal.setBrush(QPalette::Disabled, QPalette::WindowText, disabledTextColor); - pal.setBrush(QPalette::All, QPalette::ButtonText, textColor); - pal.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledTextColor); - return pal; -} - -bool QGtk::isKDE4Session() -{ - static int version = -1; - if (version == -1) - version = qgetenv("KDE_SESSION_VERSION").toInt(); - return (version == 4); -} - -void QGtk::applyCustomPaletteHash() -{ - QPalette menuPal = gtkWidgetPalette(QLS("GtkMenu")); - GdkColor gdkBg = QGtk::gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL]; - QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); - menuPal.setBrush(QPalette::Base, bgColor); - menuPal.setBrush(QPalette::Window, bgColor); - qApp->setPalette(menuPal, "QMenu"); - - QPalette toolbarPal = gtkWidgetPalette(QLS("GtkToolbar")); - qApp->setPalette(toolbarPal, "QToolBar"); - - QPalette menuBarPal = gtkWidgetPalette(QLS("GtkMenuBar")); - qApp->setPalette(menuBarPal, "QMenuBar"); -} - -static void gtkStyleSetCallback(GtkWidget*, GtkStyle*, void*) -{ - // We have to let this function return and complete the event - // loop to ensure that all gtk widgets have been styled before - // updating - QMetaObject::invokeMethod(styleScheduler(), "updateTheme", Qt::QueuedConnection); -} - -void QGtkStyleUpdateScheduler::updateTheme() -{ - static QString oldTheme(QLS("qt_not_set")); - QPixmapCache::clear(); - - QFont font = QGtk::getThemeFont(); - if (QApplication::font() != font) - qApp->setFont(font); - - if (oldTheme != getThemeName()) { - oldTheme = getThemeName(); - QPalette newPalette = qApp->style()->standardPalette(); - QApplicationPrivate::setSystemPalette(newPalette); - QApplication::setPalette(newPalette); - QGtk::initGtkWidgets(); - QGtk::applyCustomPaletteHash(); - QList<QWidget*> widgets = QApplication::allWidgets(); - // Notify all widgets that size metrics might have changed - foreach (QWidget *widget, widgets) { - QEvent e(QEvent::StyleChange); - QApplication::sendEvent(widget, &e); - } - } - QIconLoader::instance()->updateSystemTheme(); -} - -static void add_widget(GtkWidget *widget) -{ - if (widget) { - setup_gtk_widget(widget); - add_all_sub_widgets(widget); - } -} - -static void init_gtk_treeview() -{ - GtkWidget *gtkTreeView = QGtk::gtk_tree_view_new(); - QGtk::gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, QGtk::gtk_tree_view_column_new()); - QGtk::gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, QGtk::gtk_tree_view_column_new()); - QGtk::gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, QGtk::gtk_tree_view_column_new()); - add_widget(gtkTreeView); -} - - -// Fetch the application font from the pango font description -// contained in the theme. -QFont QGtk::getThemeFont() -{ - QFont font; - GtkStyle *style = gtkStyle(); - if (style && qApp->desktopSettingsAware()) - { - PangoFontDescription *gtk_font = style->font_desc; - font.setPointSizeF((float)(pango_font_description_get_size(gtk_font))/PANGO_SCALE); - - QString family = QString::fromLatin1(pango_font_description_get_family(gtk_font)); - if (!family.isEmpty()) - font.setFamily(family); - - int weight = pango_font_description_get_weight(gtk_font); - if (weight >= PANGO_WEIGHT_HEAVY) - font.setWeight(QFont::Black); - else if (weight >= PANGO_WEIGHT_BOLD) - font.setWeight(QFont::Bold); - else if (weight >= PANGO_WEIGHT_SEMIBOLD) - font.setWeight(QFont::DemiBold); - else if (weight >= PANGO_WEIGHT_NORMAL) - font.setWeight(QFont::Normal); - else - font.setWeight(QFont::Light); - - PangoStyle fontstyle = pango_font_description_get_style(gtk_font); - if (fontstyle == PANGO_STYLE_ITALIC) - font.setStyle(QFont::StyleItalic); - else if (fontstyle == PANGO_STYLE_OBLIQUE) - font.setStyle(QFont::StyleOblique); - else - font.setStyle(QFont::StyleNormal); - } - return font; -} - -GtkWidget* QGtk::gtkWidget(const QString &path) -{ - GtkWidget *widget = gtkWidgetMap()->value(path); - if (!widget) { - // Theme might have rearranged widget internals - widget = gtkWidgetMap()->value(path); - } - return widget; -} - -GtkStyle* QGtk::gtkStyle(const QString &path) -{ - if (gtkWidgetMap()->contains(path)) - return gtkWidgetMap()->value(path)->style; - return 0; -} - -static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *, gpointer) -{ - GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS; - g_object_get(gtkToolBar, "toolbar-style", &toolbar_style, NULL); - QWidgetList widgets = QApplication::allWidgets(); - for (int i = 0; i < widgets.size(); ++i) { - QWidget *widget = widgets.at(i); - if (qobject_cast<QToolButton*>(widget)) { - QEvent event(QEvent::StyleChange); - QApplication::sendEvent(widget, &event); - } - } -} - -void QGtk::initGtkWidgets() -{ - // From gtkmain.c - uid_t ruid = getuid (); - uid_t rgid = getgid (); - uid_t euid = geteuid (); - uid_t egid = getegid (); - if (ruid != euid || rgid != egid) { - qWarning("\nThis process is currently running setuid or setgid.\nGTK+ does not allow this " - "therefore Qt cannot use the GTK+ integration.\nTry launching your app using \'gksudo\', " - "\'kdesudo\' or a similar tool.\n\n" - "See http://www.gtk.org/setuid.html for more information.\n"); - return; - } - - init_gtk_window(); - - if (QGtk::gtk_init) { - - // Make all widgets respect the text direction - if (qApp->layoutDirection() == Qt::RightToLeft) - QGtk::gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL); - - if (!gtkWidgetMap()->contains(QLS("GtkButton"))) { - GtkWidget *gtkButton = QGtk::gtk_button_new(); - add_widget(gtkButton); - g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), NULL); - add_widget(QGtk::gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)); - add_widget(QGtk::gtk_hbutton_box_new()); - add_widget(QGtk::gtk_check_button_new()); - add_widget(QGtk::gtk_radio_button_new(NULL)); - add_widget(QGtk::gtk_combo_box_new()); - add_widget(QGtk::gtk_combo_box_entry_new()); - add_widget(QGtk::gtk_entry_new()); - add_widget(QGtk::gtk_frame_new(NULL)); - add_widget(QGtk::gtk_expander_new("")); - add_widget(QGtk::gtk_statusbar_new()); - add_widget(QGtk::gtk_hscale_new((GtkAdjustment*)(QGtk::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); - add_widget(QGtk::gtk_hscrollbar_new(NULL)); - add_widget(QGtk::gtk_scrolled_window_new(NULL, NULL)); - init_gtk_menu(); - add_widget(QGtk::gtk_notebook_new()); - add_widget(QGtk::gtk_progress_bar_new()); - add_widget(QGtk::gtk_spin_button_new((GtkAdjustment*) - (QGtk::gtk_adjustment_new(1, 0, 1, 0, 0, 0)), 0.1, 3)); - GtkWidget *toolbar = QGtk::gtk_toolbar_new(); - g_signal_connect (toolbar, "notify::toolbar-style", G_CALLBACK (update_toolbar_style), toolbar); - QGtk::gtk_toolbar_insert((GtkToolbar*)toolbar, QGtk::gtk_separator_tool_item_new(), -1); - add_widget(toolbar); - init_gtk_treeview(); - add_widget(QGtk::gtk_vscale_new((GtkAdjustment*)(QGtk::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); - add_widget(QGtk::gtk_vscrollbar_new(NULL)); - } - else // Rebuild map - { - // When styles change subwidgets can get rearranged - // as with the combo box. We need to update the widget map - // to reflect this; - QHash<QString, GtkWidget*> oldMap = *gtkWidgetMap(); - gtkWidgetMap()->clear(); - QHashIterator<QString, GtkWidget*> it(oldMap); - while (it.hasNext()) { - it.next(); - if (!it.key().contains(QLatin1Char('.'))) { - add_all_sub_widgets(it.value()); - } - } - } - } -} - -// ----------- Native file dialogs ----------- - -// Extract filter list from expressions of type: foo (*.a *.b *.c)" -static QStringList extract_filter(const QString &rawFilter) -{ - QString result = rawFilter; - QRegExp r(QString::fromLatin1("^([^()]*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$")); - int index = r.indexIn(result); - if (index >= 0) - result = r.cap(2); - return result.split(QLatin1Char(' ')); -} - -extern QStringList qt_make_filter_list(const QString &filter); - -static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, - const QString &dir, const QString &filter, QString *selectedFilter, - QFileDialog::Options options, bool isSaveDialog = false, - QMap<GtkFileFilter *, QString> *filterMap = 0) -{ - g_object_set(gtkFileChooser, "do-overwrite-confirmation", gboolean(!(options & QFileDialog::DontConfirmOverwrite)), NULL); - g_object_set(gtkFileChooser, "local_only", gboolean(true), NULL); - if (!filter.isEmpty()) { - QStringList filters = qt_make_filter_list(filter); - foreach (const QString &rawfilter, filters) { - GtkFileFilter *gtkFilter = QGtk::gtk_file_filter_new (); - QString name = rawfilter.left(rawfilter.indexOf(QLatin1Char('('))); - QStringList extensions = extract_filter(rawfilter); - QGtk::gtk_file_filter_set_name(gtkFilter, qPrintable(name.isEmpty() ? extensions.join(QLS(", ")) : name)); - - foreach (const QString &fileExtension, extensions) { - // Note Gtk file dialogs are by default case sensitive - // and only supports basic glob syntax so we - // rewrite .xyz to .[xX][yY][zZ] - QString caseInsensitive; - for (int i = 0 ; i < fileExtension.length() ; ++i) { - QChar ch = fileExtension.at(i); - if (ch.isLetter()) { - caseInsensitive.append( - QLatin1Char('[') + - ch.toLower() + - ch.toUpper() + - QLatin1Char(']')); - } else { - caseInsensitive.append(ch); - } - } - QGtk::gtk_file_filter_add_pattern (gtkFilter, qPrintable(caseInsensitive)); - - } - if (filterMap) - filterMap->insert(gtkFilter, rawfilter); - QGtk::gtk_file_chooser_add_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); - if (selectedFilter && (rawfilter == *selectedFilter)) - QGtk::gtk_file_chooser_set_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); - } - } - - // Using the currently active window is not entirely correct, however - // it gives more sensible behavior for applications that do not provide a - // parent - QWidget *modalFor = parent ? parent->window() : qApp->activeWindow(); - if (modalFor) { - QGtk::gtk_widget_realize(gtkFileChooser); // Creates X window - XSetTransientForHint(QGtk::gdk_x11_drawable_get_xdisplay(gtkFileChooser->window), - QGtk::gdk_x11_drawable_get_xid(gtkFileChooser->window), - modalFor->winId()); - QGtk::gdk_x11_window_set_user_time (gtkFileChooser->window, QX11Info::appUserTime()); - - } - - QFileInfo fileinfo(dir); - if (dir.isEmpty()) - fileinfo.setFile(QDir::currentPath()); - fileinfo.makeAbsolute(); - if (fileinfo.isDir()) { - QGtk::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); - } else if (isSaveDialog) { - QGtk::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.absolutePath())); - QGtk::gtk_file_chooser_set_current_name((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.fileName())); - } else { - QGtk::gtk_file_chooser_set_filename((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); - } -} - -QString QGtk::openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options) -{ - QMap<GtkFileFilter *, QString> filterMap; - GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - - setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); - - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - QApplicationPrivate::enterModal(&modal_widget); - - QString filename; - if (QGtk::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - char *gtk_filename = QGtk::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); - filename = QString::fromUtf8(gtk_filename); - g_free (gtk_filename); - if (selectedFilter) { - GtkFileFilter *gtkFilter = QGtk::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); - *selectedFilter = filterMap.value(gtkFilter); - } - } - - QApplicationPrivate::leaveModal(&modal_widget); - gtk_widget_destroy (gtkFileChooser); - return filename; -} - - -QString QGtk::openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) -{ - QMap<GtkFileFilter *, QString> filterMap; - GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - - setupGtkFileChooser(gtkFileChooser, parent, dir, QString(), 0, options); - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - QApplicationPrivate::enterModal(&modal_widget); - - QString filename; - if (QGtk::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - char *gtk_filename = QGtk::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); - filename = QString::fromUtf8(gtk_filename); - g_free (gtk_filename); - } - - QApplicationPrivate::leaveModal(&modal_widget); - gtk_widget_destroy (gtkFileChooser); - return filename; -} - -QStringList QGtk::openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options) -{ - QStringList filenames; - QMap<GtkFileFilter *, QString> filterMap; - GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); - - setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); - g_object_set(gtkFileChooser, "select-multiple", gboolean(true), NULL); - - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - QApplicationPrivate::enterModal(&modal_widget); - - if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - GSList *gtk_file_names = QGtk::gtk_file_chooser_get_filenames((GtkFileChooser*)gtkFileChooser); - for (GSList *iterator = gtk_file_names ; iterator; iterator = iterator->next) - filenames << QString::fromUtf8((const char*)iterator->data); - g_slist_free(gtk_file_names); - if (selectedFilter) { - GtkFileFilter *gtkFilter = QGtk::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); - *selectedFilter = filterMap.value(gtkFilter); - } - } - - QApplicationPrivate::leaveModal(&modal_widget); - gtk_widget_destroy (gtkFileChooser); - return filenames; -} - -QString QGtk::saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options) -{ - QMap<GtkFileFilter *, QString> filterMap; - GtkWidget *gtkFileChooser = QGtk::gtk_file_chooser_dialog_new (qPrintable(caption), - NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, true, &filterMap); - - QWidget modal_widget; - modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); - modal_widget.setParent(parent, Qt::Window); - QApplicationPrivate::enterModal(&modal_widget); - - QString filename; - if (QGtk::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { - char *gtk_filename = QGtk::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); - filename = QString::fromUtf8(gtk_filename); - g_free (gtk_filename); - if (selectedFilter) { - GtkFileFilter *gtkFilter = QGtk::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); - *selectedFilter = filterMap.value(gtkFilter); - } - } - - QApplicationPrivate::leaveModal(&modal_widget); - gtk_widget_destroy (gtkFileChooser); - return filename; -} - -QIcon QGtk::getFilesystemIcon(const QFileInfo &info) -{ - QIcon icon; - if (QGtk::gnome_vfs_init && QGtk::gnome_icon_lookup_sync) { - QGtk::gnome_vfs_init(); - GtkIconTheme *theme = QGtk::gtk_icon_theme_get_default(); - QByteArray fileurl = QUrl::fromLocalFile(info.absoluteFilePath()).toEncoded(); - char * icon_name = QGtk::gnome_icon_lookup_sync(theme, - NULL, - fileurl.data(), - NULL, - GNOME_ICON_LOOKUP_FLAGS_NONE, - NULL); - QString iconName = QString::fromUtf8(icon_name); - g_free(icon_name); - if (iconName.startsWith(QLatin1Char('/'))) - return QIcon(iconName); - return QIcon::fromTheme(iconName); - } - return icon; -} - -QT_END_NAMESPACE - -#endif // !defined(QT_NO_STYLE_GTK) diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index fabd7ca..973e682 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -3825,6 +3825,7 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption * } } break; +#ifndef QT_NO_GROUPBOX case CT_GroupBox: // Since we use a bold font we have to recalculate base width if (const QGroupBox *gb = qobject_cast<const QGroupBox*>(widget)) { @@ -3840,6 +3841,7 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption * } newSize += QSize(0, 1); break; +#endif //QT_NO_GROUPBOX case CT_RadioButton: case CT_CheckBox: newSize += QSize(0, 1); @@ -3866,7 +3868,7 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption * if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { if (!menuItem->text.isEmpty()) { - newSize.setHeight(menuItem->fontMetrics.lineSpacing()); + newSize.setHeight(menuItem->fontMetrics.height()); } } #ifndef QT_NO_COMBOBOX diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index 5886512..bf2f68e 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -4396,13 +4396,13 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid case PM_TitleBarHeight: { if (const QStyleOptionTitleBar *tb = qstyleoption_cast<const QStyleOptionTitleBar *>(opt)) { if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool) { - ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 16); + ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 16); #ifndef QT_NO_DOCKWIDGET } else if (qobject_cast<const QDockWidget*>(widget)) { - ret = qMax(widget->fontMetrics().lineSpacing(), int(QStyleHelper::dpiScaled(13))); + ret = qMax(widget->fontMetrics().height(), int(QStyleHelper::dpiScaled(13))); #endif } else { - ret = qMax(widget ? widget->fontMetrics().lineSpacing() : opt->fontMetrics.lineSpacing(), 18); + ret = qMax(widget ? widget->fontMetrics().height() : opt->fontMetrics.height(), 18); } } else { ret = int(QStyleHelper::dpiScaled(18.)); @@ -4661,7 +4661,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid case PM_ToolBarIconSize: ret = qt_guiPlatformPlugin()->platformHint(QGuiPlatformPlugin::PH_ToolBarIconSize); if (!ret) - ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); + ret = int(QStyleHelper::dpiScaled(24.)); break; case PM_TabBarIconSize: @@ -5169,13 +5169,12 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, const QWidget *widget) const { + const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QApplication::isRightToLeft()); #ifdef QT_NO_IMAGEFORMAT_PNG - Q_UNUSED(option); Q_UNUSED(widget); Q_UNUSED(sp); #else QPixmap pixmap; - const bool rtl = (option && option->direction == Qt::RightToLeft) || (!option && QApplication::isRightToLeft()); if (QApplication::desktopSettingsAware() && !QIcon::themeName().isEmpty()) { switch (sp) { diff --git a/src/gui/styles/qcommonstyle_p.h b/src/gui/styles/qcommonstyle_p.h index a905601..6122f81 100644 --- a/src/gui/styles/qcommonstyle_p.h +++ b/src/gui/styles/qcommonstyle_p.h @@ -62,25 +62,6 @@ QT_BEGIN_NAMESPACE class QStringList; -#ifdef Q_WS_X11 -class QIconTheme -{ -public: - QIconTheme(QHash <int, QString> dirList, QStringList parents) : - _dirList(dirList), _parents(parents), _valid(true){ } - QIconTheme() : _valid(false){ } - - QHash <int, QString> dirList() {return _dirList;} - QStringList parents() {return _parents;} - bool isValid() {return _valid;} - -private: - QHash <int, QString> _dirList; - QStringList _parents; - bool _valid; -}; -#endif - // Private class class QCommonStylePrivate : public QStylePrivate { diff --git a/src/gui/styles/qgtkpainter.cpp b/src/gui/styles/qgtkpainter.cpp index 05c5804..aaa029a 100644 --- a/src/gui/styles/qgtkpainter.cpp +++ b/src/gui/styles/qgtkpainter.cpp @@ -108,41 +108,41 @@ QPixmap QGtkPainter::renderTheme(uchar *bdata, uchar *wdata, const QRect &rect) return; \ QRect pixmapRect(0, 0, rect.width(), rect.height()); \ { \ - GdkPixmap *pixmap = QGtk::gdk_pixmap_new((GdkDrawable*)(m_window->window), \ + GdkPixmap *pixmap = QGtkStylePrivate::gdk_pixmap_new((GdkDrawable*)(m_window->window), \ rect.width(), rect.height(), -1); \ if (!pixmap) \ return; \ - style = QGtk::gtk_style_attach (style, m_window->window); \ - QGtk::gdk_draw_rectangle(pixmap, m_alpha ? style->black_gc : *style->bg_gc, true, \ + style = QGtkStylePrivate::gtk_style_attach (style, m_window->window); \ + QGtkStylePrivate::gdk_draw_rectangle(pixmap, m_alpha ? style->black_gc : *style->bg_gc, true, \ 0, 0, rect.width(), rect.height()); \ draw_func; \ - GdkPixbuf *imgb = QGtk::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect.width(), rect.height());\ + GdkPixbuf *imgb = QGtkStylePrivate::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect.width(), rect.height());\ if (!imgb) \ return; \ - imgb = QGtk::gdk_pixbuf_get_from_drawable(imgb, pixmap, NULL, 0, 0, 0, 0, \ + imgb = QGtkStylePrivate::gdk_pixbuf_get_from_drawable(imgb, pixmap, NULL, 0, 0, 0, 0, \ rect.width(), rect.height()); \ - uchar* bdata = (uchar*)QGtk::gdk_pixbuf_get_pixels(imgb); \ + uchar* bdata = (uchar*)QGtkStylePrivate::gdk_pixbuf_get_pixels(imgb); \ if (m_alpha) { \ - QGtk::gdk_draw_rectangle(pixmap, style->white_gc, true, 0, 0, rect.width(), rect.height()); \ + QGtkStylePrivate::gdk_draw_rectangle(pixmap, style->white_gc, true, 0, 0, rect.width(), rect.height()); \ draw_func; \ - GdkPixbuf *imgw = QGtk::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect. \ + GdkPixbuf *imgw = QGtkStylePrivate::gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, rect. \ width(), rect.height()); \ if (!imgw) \ return; \ - imgw = QGtk::gdk_pixbuf_get_from_drawable(imgw, pixmap, NULL, 0, 0, 0, 0, \ + imgw = QGtkStylePrivate::gdk_pixbuf_get_from_drawable(imgw, pixmap, NULL, 0, 0, 0, 0, \ rect.width(), rect.height()); \ - uchar* wdata = (uchar*)QGtk::gdk_pixbuf_get_pixels(imgw); \ + uchar* wdata = (uchar*)QGtkStylePrivate::gdk_pixbuf_get_pixels(imgw); \ cache = renderTheme(bdata, wdata, rect); \ - QGtk::gdk_pixbuf_unref(imgw); \ + QGtkStylePrivate::gdk_pixbuf_unref(imgw); \ } else { \ cache = renderTheme(bdata, 0, rect); \ } \ - QGtk::gdk_drawable_unref(pixmap); \ - QGtk::gdk_pixbuf_unref(imgb); \ + QGtkStylePrivate::gdk_drawable_unref(pixmap); \ + QGtkStylePrivate::gdk_pixbuf_unref(imgb); \ } QGtkPainter::QGtkPainter(QPainter *_painter) - : m_window(QGtk::gtkWidget(QLatin1String("GtkWindow"))) + : m_window(QGtkStylePrivate::gtkWidget(QLatin1String("GtkWindow"))) , m_painter(_painter) , m_alpha(true) , m_hflipped(false) @@ -185,18 +185,18 @@ GtkStyle* QGtkPainter::getStyle(GtkWidget *gtkWidget) QPixmap QGtkPainter::getIcon(const char* iconName, GtkIconSize size) { - GtkStyle *style = QGtk::gtkStyle(); - GtkIconSet* iconSet = QGtk::gtk_icon_factory_lookup_default (iconName); - GdkPixbuf* icon = QGtk::gtk_icon_set_render_icon(iconSet, + GtkStyle *style = QGtkStylePrivate::gtkStyle(); + GtkIconSet* iconSet = QGtkStylePrivate::gtk_icon_factory_lookup_default (iconName); + GdkPixbuf* icon = QGtkStylePrivate::gtk_icon_set_render_icon(iconSet, style, GTK_TEXT_DIR_LTR, GTK_STATE_NORMAL, size, NULL, "button"); - uchar* data = (uchar*)QGtk::gdk_pixbuf_get_pixels(icon); - int width = QGtk::gdk_pixbuf_get_width(icon); - int height = QGtk::gdk_pixbuf_get_height(icon); + uchar* data = (uchar*)QGtkStylePrivate::gdk_pixbuf_get_pixels(icon); + int width = QGtkStylePrivate::gdk_pixbuf_get_width(icon); + int height = QGtkStylePrivate::gdk_pixbuf_get_height(icon); QImage converted(width, height, QImage::Format_ARGB32); uchar* tdata = (uchar*)converted.bits(); @@ -208,7 +208,7 @@ QPixmap QGtkPainter::getIcon(const char* iconName, GtkIconSize size) tdata[index + QT_ALPHA] = data[index + GTK_ALPHA]; } - QGtk::gdk_pixbuf_unref(icon); + QGtkStylePrivate::gdk_pixbuf_unref(icon); // should we free iconset? return QPixmap::fromImage(converted); @@ -240,7 +240,7 @@ void QGtkPainter::paintBoxGap(GtkWidget *gtkWidget, const gchar* part, QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) + gapExtras; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_box_gap (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_box_gap (style, pixmap, state, shadow, @@ -305,7 +305,7 @@ void QGtkPainter::paintBox(GtkWidget *gtkWidget, const gchar* part, rect.size(), gtkWidget) + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_box (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_box (style, pixmap, state, shadow, @@ -356,7 +356,7 @@ void QGtkPainter::paintHline(GtkWidget *gtkWidget, const gchar* part, QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + hLineExtras + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_hline (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_hline (style, pixmap, state, NULL, @@ -383,7 +383,7 @@ void QGtkPainter::paintVline(GtkWidget *gtkWidget, const gchar* part, QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + vLineExtras +pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_vline (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_vline (style, pixmap, state, NULL, @@ -410,7 +410,7 @@ void QGtkPainter::paintExpander(GtkWidget *gtkWidget, QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + QString::number(expander_state) + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_expander (style, pixmap, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_expander (style, pixmap, state, NULL, gtkWidget, part, rect.width()/2, @@ -433,7 +433,7 @@ void QGtkPainter::paintFocus(GtkWidget *gtkWidget, const gchar* part, QPixmap cache; QString pixmapName = uniqueName(QLS(part), state, GTK_SHADOW_NONE, rect.size(), gtkWidget) + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_focus (style, pixmap, state, NULL, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_focus (style, pixmap, state, NULL, gtkWidget, part, 0, 0, @@ -458,7 +458,7 @@ void QGtkPainter::paintResizeGrip(GtkWidget *gtkWidget, const gchar* part, QPixmap cache; QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_resize_grip (style, pixmap, state, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_resize_grip (style, pixmap, state, NULL, gtkWidget, part, edge, 0, 0, rect.width(), @@ -488,7 +488,7 @@ void QGtkPainter::paintArrow(GtkWidget *gtkWidget, const gchar* part, int xOffset = m_cliprect.isValid() ? arrowrect.x() - m_cliprect.x() : 0; int yOffset = m_cliprect.isValid() ? arrowrect.y() - m_cliprect.y() : 0; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_arrow (style, pixmap, state, shadow, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_arrow (style, pixmap, state, shadow, >kCliprect, gtkWidget, part, @@ -515,7 +515,7 @@ void QGtkPainter::paintHandle(GtkWidget *gtkWidget, const gchar* part, const QRe QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) + QString::number(orientation); if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_handle (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_handle (style, pixmap, state, shadow, @@ -543,7 +543,7 @@ void QGtkPainter::paintSlider(GtkWidget *gtkWidget, const gchar* part, const QRe QPixmap cache; QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size(), gtkWidget) + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_slider (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_slider (style, pixmap, state, shadow, @@ -574,7 +574,7 @@ void QGtkPainter::paintShadow(GtkWidget *gtkWidget, const gchar* part, QPixmap cache; QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_shadow(style, pixmap, state, shadow, NULL, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_shadow(style, pixmap, state, shadow, NULL, gtkWidget, part, 0, 0, rect.width(), rect.height())); if (m_usePixmapCache) QPixmapCache::insert(pixmapName, cache); @@ -593,7 +593,7 @@ void QGtkPainter::paintFlatBox(GtkWidget *gtkWidget, const gchar* part, QPixmap cache; QString pixmapName = uniqueName(QLS(part), state, shadow, rect.size()) + pmKey; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_flat_box (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_flat_box (style, pixmap, state, shadow, @@ -622,7 +622,7 @@ void QGtkPainter::paintExtention(GtkWidget *gtkWidget, pixmapName += QString::number(gap_pos); if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_extension (style, pixmap, state, shadow, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_extension (style, pixmap, state, shadow, NULL, gtkWidget, (gchar*)part, 0, 0, rect.width(), @@ -651,7 +651,7 @@ void QGtkPainter::paintOption(GtkWidget *gtkWidget, const QRect &radiorect, int xOffset = m_cliprect.isValid() ? radiorect.x() - m_cliprect.x() : 0; int yOffset = m_cliprect.isValid() ? radiorect.y() - m_cliprect.y() : 0; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_option(style, pixmap, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_option(style, pixmap, state, shadow, >kCliprect, gtkWidget, @@ -683,7 +683,7 @@ void QGtkPainter::paintCheckbox(GtkWidget *gtkWidget, const QRect &checkrect, int xOffset = m_cliprect.isValid() ? checkrect.x() - m_cliprect.x() : 0; int yOffset = m_cliprect.isValid() ? checkrect.y() - m_cliprect.y() : 0; if (!m_usePixmapCache || !QPixmapCache::find(pixmapName, cache)) { - DRAW_TO_CACHE(QGtk::gtk_paint_check (style, + DRAW_TO_CACHE(QGtkStylePrivate::gtk_paint_check (style, pixmap, state, shadow, diff --git a/src/gui/styles/qgtkpainter_p.h b/src/gui/styles/qgtkpainter_p.h index 0e8ffe2..cbc96c0 100644 --- a/src/gui/styles/qgtkpainter_p.h +++ b/src/gui/styles/qgtkpainter_p.h @@ -56,11 +56,11 @@ #include <QtCore/qglobal.h> #if !defined(QT_NO_STYLE_GTK) -#include "gtksymbols_p.h" #include <QtGui/QCleanlooksStyle> #include <QtGui/QPainter> #include <QtGui/QPalette> #include <QtGui/QFont> +#include <private/qgtkstyle_p.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index 414580e..1c78a47 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -69,28 +69,14 @@ #include <QtGui/QTreeView> #include <qpixmapcache.h> #undef signals // Collides with GTK stymbols -#include "qgtkpainter_p.h" -#include "qstylehelper_p.h" - +#include <private/qgtkpainter_p.h> +#include <private/qstylehelper_p.h> +#include <private/qgtkstyle_p.h> #include <private/qcleanlooksstyle_p.h> QT_BEGIN_NAMESPACE -typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, - const QString &filter, QString *selectedFilter, QFileDialog::Options options); -typedef QString (*_qt_filedialog_open_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, - const QString &filter, QString *selectedFilter, QFileDialog::Options options); -typedef QString (*_qt_filedialog_save_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, - const QString &filter, QString *selectedFilter, QFileDialog::Options options); -typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, - QFileDialog::Options options); - -extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; -extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; -extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; -extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; - static const char * const dock_widget_close_xpm[] = { "11 13 5 1", @@ -137,57 +123,18 @@ static const char * const dock_widget_restore_xpm[] = " " }; - -class QGtkStyleFilter : public QObject -{ -public: - QGtkStyleFilter() {} -private: - bool eventFilter(QObject *obj, QEvent *e); -}; - -bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e) -{ - if (e->type() == QEvent::ApplicationPaletteChange) { - // Only do this the first time since this will also - // generate applicationPaletteChange events - if (!qt_app_palettes_hash() || qt_app_palettes_hash()->isEmpty()) { - QGtk::applyCustomPaletteHash(); - } - } - return QObject::eventFilter(obj, e); -} - -class QGtkStylePrivate : public QCleanlooksStylePrivate -{ - Q_DECLARE_PUBLIC(QGtkStyle) -public: - QGtkStylePrivate() - : QCleanlooksStylePrivate() - { - QGtk::initGtkWidgets(); - if (QGtk::isThemeAvailable()) - qApp->installEventFilter(&filter); - - } - QGtkStyleFilter filter; -}; - static const int groupBoxBottomMargin = 2; // space below the groupbox static const int groupBoxTitleMargin = 6; // space between contents and title static const int groupBoxTopMargin = 2; -// Get size of the arrow controls in a GtkSpinButton -static int spinboxArrowSize() +QString QGtkStyle::getGConfString(const QString &value, const QString &fallback) { - const int MIN_ARROW_WIDTH = 6; - GtkWidget *spinButton = QGtk::gtkWidget(QLS("GtkSpinButton")); - GtkStyle *style = spinButton->style; - gint size = QGtk::pango_font_description_get_size (style->font_desc); - gint arrow_size; - arrow_size = qMax(PANGO_PIXELS (size), MIN_ARROW_WIDTH) + style->xthickness; - arrow_size += arrow_size%2 + 1; - return arrow_size; + return QGtkStylePrivate::getGConfString(value, fallback); +} + +bool QGtkStyle::getGConfBool(const QString &key, bool fallback) +{ + return QGtkStylePrivate::getGConfBool(key, fallback); } static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50) @@ -233,8 +180,23 @@ static GdkColor fromQColor(const QColor &color) QGtkStyle::QGtkStyle() : QCleanlooksStyle(*new QGtkStylePrivate) { + Q_D(QGtkStyle); + d->init(); +} + +/*! + \internal + + Constructs a QGtkStyle object. +*/ +QGtkStyle::QGtkStyle(QGtkStylePrivate &dd) + : QCleanlooksStyle(dd) +{ + Q_D(QGtkStyle); + d->init(); } + /*! Destroys the QGtkStyle object. */ @@ -247,11 +209,13 @@ QGtkStyle::~QGtkStyle() */ QPalette QGtkStyle::standardPalette() const { + Q_D(const QGtkStyle); + QPalette palette = QCleanlooksStyle::standardPalette(); - if (QGtk::isThemeAvailable()) { - GtkStyle *style = QGtk::gtkStyle(); - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); - GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry")); + if (d->isThemeAvailable()) { + GtkStyle *style = d->gtkStyle(); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton")); + GtkWidget *gtkEntry = d->getTextColorWidget(); GdkColor gdkBg, gdkBase, gdkText, gdkForeground, gdkSbg, gdkSfg; QColor bg, base, text, fg, highlight, highlightText; @@ -281,12 +245,12 @@ QPalette QGtkStyle::standardPalette() const palette.setColor(QPalette::Base, base); QColor alternateRowColor = palette.base().color().lighter(93); // ref gtkstyle.c draw_flat_box - GtkWidget *gtkTreeView = QGtk::gtkWidget(QLS("GtkTreeView")); + GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView")); GdkColor *gtkAltBase = NULL; - QGtk::gtk_widget_style_get(gtkTreeView, "odd-row-color", >kAltBase, NULL); + d->gtk_widget_style_get(gtkTreeView, "odd-row-color", >kAltBase, NULL); if (gtkAltBase) { alternateRowColor = QColor(gtkAltBase->red>>8, gtkAltBase->green>>8, gtkAltBase->blue>>8); - QGtk::gdk_color_free(gtkAltBase); + d->gdk_color_free(gtkAltBase); } palette.setColor(QPalette::AlternateBase, alternateRowColor); @@ -306,7 +270,8 @@ QPalette QGtkStyle::standardPalette() const highlightText.setHsv(highlightText.hue(), 0, highlightText.value(), highlightText.alpha()); palette.setColor(QPalette::Disabled, QPalette::Highlight, highlight); palette.setColor(QPalette::Disabled, QPalette::HighlightedText, highlightText); - style = QGtk::gtk_rc_get_style_by_paths(QGtk::gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", Q_GTK_TYPE_WINDOW); + style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", + d->gtk_window_get_type()); if (style) { gdkText = style->fg[GTK_STATE_NORMAL]; text = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); @@ -321,10 +286,12 @@ QPalette QGtkStyle::standardPalette() const */ void QGtkStyle::polish(QPalette &palette) { + Q_D(QGtkStyle); + // QCleanlooksStyle will alter the palette, hence we do // not want to polish the palette unless we are using it as // the fallback - if (!QGtk::isThemeAvailable()) + if (!d->isThemeAvailable()) QCleanlooksStyle::polish(palette); else palette = palette.resolve(standardPalette()); @@ -335,19 +302,21 @@ void QGtkStyle::polish(QPalette &palette) */ void QGtkStyle::polish(QApplication *app) { + Q_D(QGtkStyle); + QCleanlooksStyle::polish(app); // Custom fonts and palettes with QtConfig are intentionally // not supported as these should be entirely determined by // current Gtk settings - if (app->desktopSettingsAware() && QGtk::isThemeAvailable()) { + if (app->desktopSettingsAware() && d->isThemeAvailable()) { QApplicationPrivate::setSystemPalette(standardPalette()); - QApplicationPrivate::setSystemFont(QGtk::getThemeFont()); - QGtk::applyCustomPaletteHash(); - if (!QGtk::isKDE4Session()) { - qt_filedialog_open_filename_hook = &QGtk::openFilename; - qt_filedialog_save_filename_hook = &QGtk::saveFilename; - qt_filedialog_open_filenames_hook = &QGtk::openFilenames; - qt_filedialog_existing_directory_hook = &QGtk::openDirectory; + QApplicationPrivate::setSystemFont(d->getThemeFont()); + d->applyCustomPaletteHash(); + if (!d->isKDE4Session()) { + qt_filedialog_open_filename_hook = &QGtkStylePrivate::openFilename; + qt_filedialog_save_filename_hook = &QGtkStylePrivate::saveFilename; + qt_filedialog_open_filenames_hook = &QGtkStylePrivate::openFilenames; + qt_filedialog_existing_directory_hook = &QGtkStylePrivate::openDirectory; } } } @@ -357,11 +326,13 @@ void QGtkStyle::polish(QApplication *app) */ void QGtkStyle::unpolish(QApplication *app) { + Q_D(QGtkStyle); + QCleanlooksStyle::unpolish(app); QPixmapCache::clear(); - if (app->desktopSettingsAware() && QGtk::isThemeAvailable() - && !QGtk::isKDE4Session()) { + if (app->desktopSettingsAware() && d->isThemeAvailable() + && !d->isKDE4Session()) { qt_filedialog_open_filename_hook = 0; qt_filedialog_save_filename_hook = 0; qt_filedialog_open_filenames_hook = 0; @@ -375,8 +346,10 @@ void QGtkStyle::unpolish(QApplication *app) void QGtkStyle::polish(QWidget *widget) { + Q_D(QGtkStyle); + QCleanlooksStyle::polish(widget); - if (!QGtk::isThemeAvailable()) + if (!d->isThemeAvailable()) return; if (qobject_cast<QAbstractButton*>(widget) || qobject_cast<QToolButton*>(widget) @@ -404,21 +377,22 @@ void QGtkStyle::unpolish(QWidget *widget) \reimp */ int QGtkStyle::pixelMetric(PixelMetric metric, - const QStyleOption *option, const QWidget *widget) const { - if (!QGtk::isThemeAvailable()) + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) return QCleanlooksStyle::pixelMetric(metric, option, widget); switch (metric) { case PM_DefaultFrameWidth: if (qobject_cast<const QFrame*>(widget)) { if (GtkStyle *style = - QGtk::gtk_rc_get_style_by_paths(QGtk::gtk_settings_get_default(), + d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "*.GtkScrolledWindow", "*.GtkScrolledWindow", - Q_GTK_TYPE_WINDOW)) + d->gtk_window_get_type())) return qMax(style->xthickness, style->ythickness); } return 2; @@ -439,16 +413,16 @@ int QGtkStyle::pixelMetric(PixelMetric metric, return 0; case PM_ButtonShiftHorizontal: { - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton")); guint horizontal_shift; - QGtk::gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL); + d->gtk_widget_style_get(gtkButton, "child-displacement-x", &horizontal_shift, NULL); return horizontal_shift; } case PM_ButtonShiftVertical: { - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton")); guint vertical_shift; - QGtk::gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL); + d->gtk_widget_style_get(gtkButton, "child-displacement-y", &vertical_shift, NULL); return vertical_shift; } @@ -456,18 +430,18 @@ int QGtkStyle::pixelMetric(PixelMetric metric, return 0; case PM_MenuPanelWidth: { - GtkWidget *gtkMenu = QGtk::gtkWidget(QLS("GtkMenu")); + GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu")); guint horizontal_padding = 0; // horizontal-padding is used by Maemo to get thicker borders - if (!QGtk::gtk_check_version(2, 10, 0)) - QGtk::gtk_widget_style_get(gtkMenu, "horizontal-padding", &horizontal_padding, NULL); + if (!d->gtk_check_version(2, 10, 0)) + d->gtk_widget_style_get(gtkMenu, "horizontal-padding", &horizontal_padding, NULL); int padding = qMax<int>(gtkMenu->style->xthickness, horizontal_padding); return padding; } case PM_ButtonIconSize: { int retVal = 24; - GtkSettings *settings = QGtk::gtk_settings_get_default(); + GtkSettings *settings = d->gtk_settings_get_default(); gchararray icon_sizes; g_object_get(settings, "gtk-icon-sizes", &icon_sizes, NULL); QStringList values = QString(QLS(icon_sizes)).split(QLatin1Char(':')); @@ -513,9 +487,9 @@ int QGtkStyle::pixelMetric(PixelMetric metric, case PM_SliderThickness: case PM_SliderControlThickness: { - GtkWidget *gtkScale = QGtk::gtkWidget(QLS("GtkHScale")); + GtkWidget *gtkScale = d->gtkWidget(QLS("GtkHScale")); gint val; - QGtk::gtk_widget_style_get(gtkScale, "slider-width", &val, NULL); + d->gtk_widget_style_get(gtkScale, "slider-width", &val, NULL); if (metric == PM_SliderControlThickness) return val + 2*gtkScale->style->ythickness; return val; @@ -524,8 +498,8 @@ int QGtkStyle::pixelMetric(PixelMetric metric, case PM_ScrollBarExtent: { gint sliderLength; gint trough_border; - GtkWidget *hScrollbar = QGtk::gtkWidget(QLS("GtkHScrollbar")); - QGtk::gtk_widget_style_get(hScrollbar, + GtkWidget *hScrollbar = d->gtkWidget(QLS("GtkHScrollbar")); + d->gtk_widget_style_get(hScrollbar, "trough-border", &trough_border, "slider-width", &sliderLength, NULL); @@ -537,35 +511,35 @@ int QGtkStyle::pixelMetric(PixelMetric metric, case PM_SliderLength: gint val; - QGtk::gtk_widget_style_get(QGtk::gtkWidget(QLS("GtkHScale")), "slider-length", &val, NULL); + d->gtk_widget_style_get(d->gtkWidget(QLS("GtkHScale")), "slider-length", &val, NULL); return val; case PM_ExclusiveIndicatorWidth: case PM_ExclusiveIndicatorHeight: case PM_IndicatorWidth: case PM_IndicatorHeight: { - GtkWidget *gtkCheckButton = QGtk::gtkWidget(QLS("GtkCheckButton")); + GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton")); gint size, spacing; - QGtk::gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, "indicator-size", &size, NULL); + d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, "indicator-size", &size, NULL); return size + 2 * spacing; } case PM_MenuBarVMargin: { - GtkWidget *gtkMenubar = QGtk::gtkWidget(QLS("GtkMenuBar")); + GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar")); return qMax(0, gtkMenubar->style->ythickness); } case PM_ScrollView_ScrollBarSpacing: { gint spacing = 3; - GtkWidget *gtkScrollWindow = QGtk::gtkWidget(QLS("GtkScrolledWindow")); + GtkWidget *gtkScrollWindow = d->gtkWidget(QLS("GtkScrolledWindow")); Q_ASSERT(gtkScrollWindow); - QGtk::gtk_widget_style_get(gtkScrollWindow, "scrollbar-spacing", &spacing, NULL); + d->gtk_widget_style_get(gtkScrollWindow, "scrollbar-spacing", &spacing, NULL); return spacing; } case PM_SubMenuOverlap: { gint offset = 0; - GtkWidget *gtkMenu = QGtk::gtkWidget(QLS("GtkMenu")); - QGtk::gtk_widget_style_get(gtkMenu, "horizontal-offset", &offset, NULL); + GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu")); + d->gtk_widget_style_get(gtkMenu, "horizontal-offset", &offset, NULL); return offset; } default: @@ -580,7 +554,9 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg QStyleHintReturn *returnData = 0) const { - if (!QGtk::isThemeAvailable()) + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) return QCleanlooksStyle::styleHint(hint, option, widget, returnData); switch (hint) { @@ -588,7 +564,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg case SH_DialogButtonLayout: { int ret = QDialogButtonBox::GnomeLayout; gboolean alternateOrder = 0; - GtkSettings *settings = QGtk::gtk_settings_get_default(); + GtkSettings *settings = d->gtk_settings_get_default(); g_object_get(settings, "gtk-alternative-button-order", &alternateOrder, NULL); if (alternateOrder) @@ -601,9 +577,9 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg case SH_ToolButtonStyle: { - if (QGtk::isKDE4Session()) + if (d->isKDE4Session()) return QCleanlooksStyle::styleHint(hint, option, widget, returnData); - GtkWidget *gtkToolbar = QGtk::gtkWidget(QLS("GtkToolbar")); + GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar")); GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS; g_object_get(gtkToolbar, "toolbar-style", &toolbar_style, NULL); switch (toolbar_style) { @@ -626,9 +602,9 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg return int(false); case SH_ComboBox_Popup: { - GtkWidget *gtkComboBox = QGtk::gtkWidget(QLS("GtkComboBox")); + GtkWidget *gtkComboBox = d->gtkWidget(QLS("GtkComboBox")); gboolean appears_as_list; - QGtk::gtk_widget_style_get((GtkWidget*)gtkComboBox, "appears-as-list", &appears_as_list, NULL); + d->gtk_widget_style_get((GtkWidget*)gtkComboBox, "appears-as-list", &appears_as_list, NULL); return appears_as_list ? 0 : 1; } @@ -640,7 +616,7 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg case SH_Menu_SubMenuPopupDelay: { gint delay = 225; - GtkSettings *settings = QGtk::gtk_settings_get_default(); + GtkSettings *settings = d->gtk_settings_get_default(); g_object_get(settings, "gtk-menu-popup-delay", &delay, NULL); return delay; } @@ -649,15 +625,15 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg gboolean scrollbars_within_bevel = false; if (widget && widget->isWindow()) scrollbars_within_bevel = true; - else if (!QGtk::gtk_check_version(2, 12, 0)) { - GtkWidget *gtkScrollWindow = QGtk::gtkWidget(QLS("GtkScrolledWindow")); - QGtk::gtk_widget_style_get(gtkScrollWindow, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL); + else if (!d->gtk_check_version(2, 12, 0)) { + GtkWidget *gtkScrollWindow = d->gtkWidget(QLS("GtkScrolledWindow")); + d->gtk_widget_style_get(gtkScrollWindow, "scrollbars-within-bevel", &scrollbars_within_bevel, NULL); } return !scrollbars_within_bevel; } case SH_DialogButtonBox_ButtonsHaveIcons: { - static bool buttonsHaveIcons = QGtk::getGConfBool(QLS("/desktop/gnome/interface/buttons_have_icons")); + static bool buttonsHaveIcons = d->getGConfBool(QLS("/desktop/gnome/interface/buttons_have_icons")); return buttonsHaveIcons; } @@ -670,17 +646,18 @@ int QGtkStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidg \reimp */ void QGtkStyle::drawPrimitive(PrimitiveElement element, - const QStyleOption *option, QPainter *painter, const QWidget *widget) const { - if (!QGtk::isThemeAvailable()) { + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) { QCleanlooksStyle::drawPrimitive(element, option, painter, widget); return; } - GtkStyle* style = QGtk::gtkStyle(); + GtkStyle* style = d->gtkStyle(); QGtkPainter gtkPainter(painter); switch (element) { @@ -715,10 +692,10 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, else if (option->state & State_Raised) shadow_type = GTK_SHADOW_OUT; - GtkStyle *style = QGtk::gtk_rc_get_style_by_paths(QGtk::gtk_settings_get_default(), - "*.GtkScrolledWindow", "*.GtkScrolledWindow", Q_GTK_TYPE_WINDOW); + GtkStyle *style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), + "*.GtkScrolledWindow", "*.GtkScrolledWindow", d->gtk_window_get_type()); if (style) - gtkFramePainter.paintShadow(QGtk::gtkWidget(QLS("GtkFrame")), "viewport", pmRect, + gtkFramePainter.paintShadow(d->gtkWidget(QLS("GtkFrame")), "viewport", pmRect, option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE, shadow_type, style); QPixmapCache::insert(pmKey, pixmap); @@ -745,8 +722,9 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, break; case PE_PanelTipLabel: { - GtkWidget *gtkWindow = QGtk::gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed - style = QGtk::gtk_rc_get_style_by_paths(QGtk::gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", Q_GTK_TYPE_WINDOW); + GtkWidget *gtkWindow = d->gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed + style = d->gtk_rc_get_style_by_paths(d->gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", + d->gtk_window_get_type()); gtkPainter.paintFlatBox(gtkWindow, "tooltip", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_NONE, style); } break; @@ -759,8 +737,8 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, break; } GtkShadowType shadow_type; - GtkWidget *gtkStatusbarFrame = QGtk::gtkWidget(QLS("GtkStatusbar.GtkFrame")); - QGtk::gtk_widget_style_get(gtkStatusbarFrame->parent, "shadow-type", &shadow_type, NULL); + GtkWidget *gtkStatusbarFrame = d->gtkWidget(QLS("GtkStatusbar.GtkFrame")); + d->gtk_widget_style_get(gtkStatusbarFrame->parent, "shadow-type", &shadow_type, NULL); gtkPainter.paintShadow(gtkStatusbarFrame, "frame", option->rect, GTK_STATE_NORMAL, shadow_type, gtkStatusbarFrame->style); } @@ -768,7 +746,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, case PE_IndicatorHeaderArrow: if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { - GtkWidget *gtkTreeHeader = QGtk::gtkWidget(QLS("GtkTreeView.GtkButton")); + GtkWidget *gtkTreeHeader = d->gtkWidget(QLS("GtkTreeView.GtkButton")); GtkStateType state = gtkPainter.gtkState(option); style = gtkTreeHeader->style; GtkArrowType type = GTK_ARROW_UP; @@ -806,7 +784,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, rect.translate(2, 0); GtkExpanderStyle openState = GTK_EXPANDER_EXPANDED; GtkExpanderStyle closedState = GTK_EXPANDER_COLLAPSED; - GtkWidget *gtkTreeView = QGtk::gtkWidget(QLS("GtkTreeView")); + GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView")); GtkStateType state = GTK_STATE_NORMAL; if (!(option->state & State_Enabled)) @@ -842,7 +820,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, case PE_IndicatorToolBarSeparator: { const int margin = 6; - GtkWidget *gtkSeparator = QGtk::gtkWidget(QLS("GtkToolbar.GtkSeparatorToolItem")); + GtkWidget *gtkSeparator = d->gtkWidget(QLS("GtkToolbar.GtkSeparatorToolItem")); if (option->state & State_Horizontal) { const int offset = option->rect.width()/2; QRect rect = option->rect.adjusted(offset, margin, 0, -margin); @@ -862,9 +840,9 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, break; case PE_IndicatorToolBarHandle: { - GtkWidget *gtkToolbar = QGtk::gtkWidget(QLS("GtkToolbar")); + GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar")); GtkShadowType shadow_type; - QGtk::gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL); + d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL); //Note when the toolbar is horizontal, the handle is vertical painter->setClipRect(option->rect); gtkPainter.paintHandle(gtkToolbar, "toolbar", option->rect.adjusted(-1, -1 ,0 ,1), @@ -910,14 +888,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, GtkStateType state = gtkPainter.gtkState(option); QColor arrowColor = option->palette.buttonText().color(); - GtkWidget *gtkArrow = QGtk::gtkWidget(QLS("GtkArrow")); + GtkWidget *gtkArrow = d->gtkWidget(QLS("GtkArrow")); GdkColor color = fromQColor(arrowColor); - QGtk::gtk_widget_modify_fg (gtkArrow, state, &color); + d->gtk_widget_modify_fg (gtkArrow, state, &color); gtkPainter.paintArrow(gtkArrow, "button", arrowRect, type, state, shadow, FALSE, gtkArrow->style, QString::number(arrowColor.rgba(), 16)); // Passing NULL will revert the color change - QGtk::gtk_widget_modify_fg (gtkArrow, state, NULL); + d->gtk_widget_modify_fg (gtkArrow, state, NULL); } break; @@ -926,7 +904,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, break; case PE_PanelMenu: { - GtkWidget *gtkMenu = QGtk::gtkWidget(QLS("GtkMenu")); + GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu")); gtkPainter.setAlphaSupport(false); // Note, alpha disabled for performance reasons gtkPainter.paintBox(gtkMenu, "menu", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, gtkMenu->style, QString()); } @@ -938,7 +916,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, // This is only used by floating tool bars if (qobject_cast<const QToolBar *>(widget)) { - GtkWidget *gtkMenubar = QGtk::gtkWidget(QLS("GtkMenuBar")); + GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar")); gtkPainter.paintBox( gtkMenubar, "toolbar", option->rect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, style); gtkPainter.paintBox( gtkMenubar, "menu", option->rect, @@ -947,13 +925,13 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, break; case PE_FrameLineEdit: { - GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry")); + GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry")); gboolean interior_focus; gint focus_line_width; QRect rect = option->rect; - QGtk::gtk_widget_style_get(gtkEntry, + d->gtk_widget_style_get(gtkEntry, "interior-focus", &interior_focus, "focus-line-width", &focus_line_width, NULL); @@ -981,7 +959,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, case PE_PanelLineEdit: if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) { - GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry")); + GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry")); if (panel->lineWidth > 0) proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget); uint resolve_mask = option->palette.resolve(); @@ -999,54 +977,58 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, case PE_FrameTabWidget: if (const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<const QStyleOptionTabWidgetFrame*>(option)) { - GtkWidget *gtkNotebook = QGtk::gtkWidget(QLS("GtkNotebook")); + GtkWidget *gtkNotebook = d->gtkWidget(QLS("GtkNotebook")); style = gtkPainter.getStyle(gtkNotebook); gtkPainter.setAlphaSupport(false); GtkShadowType shadow = GTK_SHADOW_OUT; GtkStateType state = GTK_STATE_NORMAL; // Only state supported by gtknotebook - if (const QTabWidget *tabwidget = qobject_cast<const QTabWidget*>(widget)) { - // We should introduce QStyleOptionTabWidgetFrameV2 to obtain this information - // No gap if we do not show the actual tabs - QTabBar *tabBar = tabwidget->findChild<QTabBar*>(); - if (tabwidget->count() > 0 && tabBar->isVisible()) { - QRect tabRect = tabBar->tabRect(tabBar->currentIndex()); - int begin = 0, size = 0; - GtkPositionType frameType = GTK_POS_TOP; - QTabBar::Shape shape = frame->shape; - if (shape == QTabBar::RoundedNorth || shape == QTabBar::RoundedSouth) { - begin = option->direction == Qt::LeftToRight ? - frame->leftCornerWidgetSize.width() + tabRect.left() : - frame->rect.width() - frame->tabBarSize.width() + tabRect.left() - - frame->rightCornerWidgetSize.width(); - size = tabRect.width(); - frameType = (shape == QTabBar::RoundedNorth) ? GTK_POS_TOP : GTK_POS_BOTTOM; - } else { - begin = frame->leftCornerWidgetSize.height() + tabRect.top(); - size = tabRect.height(); - frameType = (shape == QTabBar::RoundedWest) ? GTK_POS_LEFT : GTK_POS_RIGHT; - } - gtkPainter.paintBoxGap(gtkNotebook, "notebook", option->rect, state, shadow, frameType, - begin, size, style); - break; // done + bool reverse = (option->direction == Qt::RightToLeft); + QGtkStylePrivate::gtk_widget_set_direction(gtkNotebook, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + if (const QStyleOptionTabWidgetFrameV2 *tabframe = qstyleoption_cast<const QStyleOptionTabWidgetFrameV2*>(option)) { + GtkPositionType frameType = GTK_POS_TOP; + QTabBar::Shape shape = frame->shape; + int gapStart = 0; + int gapSize = 0; + if (shape == QTabBar::RoundedNorth || shape == QTabBar::RoundedSouth) { + frameType = (shape == QTabBar::RoundedNorth) ? GTK_POS_TOP : GTK_POS_BOTTOM; + gapStart = tabframe->selectedTabRect.left(); + gapSize = tabframe->selectedTabRect.width(); + } else { + frameType = (shape == QTabBar::RoundedWest) ? GTK_POS_LEFT : GTK_POS_RIGHT; + gapStart = tabframe->selectedTabRect.y(); + gapSize = tabframe->selectedTabRect.height(); } + gtkPainter.paintBoxGap(gtkNotebook, "notebook", option->rect, state, shadow, frameType, + gapStart, gapSize, style); + break; // done } + // Note this is only the fallback option gtkPainter.paintBox(gtkNotebook, "notebook", option->rect, state, shadow, style); } break; - case PE_PanelButtonCommand: { + case PE_PanelButtonCommand: + case PE_PanelButtonTool: { bool isDefault = false; + bool isTool = (element == PE_PanelButtonTool); if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton*>(option)) isDefault = btn->features & QStyleOptionButton::DefaultButton; + // don't draw a frame for tool buttons that have the autoRaise flag and are not enabled or on + if (isTool && !(option->state & State_Enabled || option->state & State_On) && (option->state & State_AutoRaise)) + break; + // don't draw a frame for dock widget buttons, unless we are hovering + if (widget && widget->inherits("QDockWidgetTitleButton") && !(option->state & State_MouseOver)) + break; + GtkStateType state = gtkPainter.gtkState(option); if (option->state & State_On || option->state & State_Sunken) state = GTK_STATE_ACTIVE; - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(isTool ? QLS("GtkToolButton.GtkButton") : QLS("GtkButton")); gint focusWidth, focusPad; gboolean interiorFocus = false; - QGtk::gtk_widget_style_get (gtkButton, + d->gtk_widget_style_get (gtkButton, "focus-line-width", &focusWidth, "focus-padding", &focusPad, "interior-focus", &interiorFocus, NULL); @@ -1099,14 +1081,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, else shadow = GTK_SHADOW_OUT; - GtkWidget *gtkRadioButton = QGtk::gtkWidget(QLS("GtkRadioButton")); + GtkWidget *gtkRadioButton = d->gtkWidget(QLS("GtkRadioButton")); gint spacing; - QGtk::gtk_widget_style_get(gtkRadioButton, "indicator-spacing", &spacing, NULL); + d->gtk_widget_style_get(gtkRadioButton, "indicator-spacing", &spacing, NULL); QRect buttonRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing); gtkPainter.setClipRect(option->rect); // ### Note: Ubuntulooks breaks when the proper widget is passed // Murrine engine requires a widget not to get RGBA check - warnings - GtkWidget *gtkCheckButton = QGtk::gtkWidget(QLS("GtkCheckButton")); + GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton")); gtkPainter.paintOption(gtkCheckButton , buttonRect, state, shadow, gtkRadioButton->style, QLS("radiobutton")); } @@ -1128,12 +1110,12 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element, int spacing; - GtkWidget *gtkCheckButton = QGtk::gtkWidget(QLS("GtkCheckButton")); + GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton")); // Some styles such as aero-clone assume they can paint in the spacing area gtkPainter.setClipRect(option->rect); - QGtk::gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, NULL); + d->gtk_widget_style_get(gtkCheckButton, "indicator-spacing", &spacing, NULL); QRect checkRect = option->rect.adjusted(spacing, spacing, -spacing, -spacing); @@ -1200,12 +1182,14 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom QPainter *painter, const QWidget *widget) const { - if (!QGtk::isThemeAvailable()) { + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) { QCleanlooksStyle::drawComplexControl(control, option, painter, widget); return; } - GtkStyle* style = QGtk::gtkStyle(); + GtkStyle* style = d->gtkStyle(); QGtkPainter gtkPainter(painter); QColor button = option->palette.button().color(); QColor dark; @@ -1260,7 +1244,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) { // Draw prelight background - GtkWidget *gtkCheckButton = QGtk::gtkWidget(QLS("GtkCheckButton")); + GtkWidget *gtkCheckButton = d->gtkWidget(QLS("GtkCheckButton")); if (option->state & State_MouseOver) { QRect bgRect = textRect | checkBoxRect; @@ -1336,14 +1320,14 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom QString comboBoxPath = QLS(comboBox->editable ? "GtkComboBoxEntry" : "GtkComboBox"); // We use the gtk widget to position arrows and separators for us - GtkWidget *gtkCombo = QGtk::gtkWidget(comboBoxPath); + GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath); GtkAllocation geometry = {0, 0, option->rect.width(), option->rect.height()}; - QGtk::gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); - QGtk::gtk_widget_size_allocate(gtkCombo, &geometry); + d->gtk_widget_set_direction(gtkCombo, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + d->gtk_widget_size_allocate(gtkCombo, &geometry); QString buttonPath = comboBoxPath + QLS(".GtkToggleButton"); - GtkWidget *gtkToggleButton = QGtk::gtkWidget(buttonPath); - QGtk::gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + GtkWidget *gtkToggleButton = d->gtkWidget(buttonPath); + d->gtk_widget_set_direction(gtkToggleButton, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); if (gtkToggleButton && (appears_as_list || comboBox->editable)) { if (focus) GTK_WIDGET_SET_FLAGS(gtkToggleButton, GTK_HAS_FOCUS); @@ -1351,8 +1335,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom if (comboBox->editable || appears_as_list) { GtkStateType frameState = (state == GTK_STATE_PRELIGHT) ? GTK_STATE_NORMAL : state; QString entryPath = QLS(comboBox->editable ? "GtkComboBoxEntry.GtkEntry" : "GtkComboBox.GtkFrame"); - GtkWidget *gtkEntry = QGtk::gtkWidget(entryPath); - QGtk::gtk_widget_set_direction(gtkEntry, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + GtkWidget *gtkEntry = d->gtkWidget(entryPath); + d->gtk_widget_set_direction(gtkEntry, reverse ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); QRect frameRect = option->rect; if (reverse) @@ -1421,7 +1405,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom // Draw the separator between label and arrows QString vSeparatorPath = buttonPath + QLS(".GtkHBox.GtkVSeparator"); - if (GtkWidget *gtkVSeparator = QGtk::gtkWidget(vSeparatorPath)) { + if (GtkWidget *gtkVSeparator = d->gtkWidget(vSeparatorPath)) { QRect vLineRect(gtkVSeparator->allocation.x, gtkVSeparator->allocation.y, gtkVSeparator->allocation.width, @@ -1433,7 +1417,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom gint interiorFocus = true; - QGtk::gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL); + d->gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL); int xt = interiorFocus ? gtkToggleButton->style->xthickness : 0; int yt = interiorFocus ? gtkToggleButton->style->ythickness : 0; if (focus && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) @@ -1457,14 +1441,14 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom QString arrowPath = comboBoxPath + QLS(appears_as_list ? ".GtkToggleButton.GtkArrow" : ".GtkToggleButton.GtkHBox.GtkArrow"); - GtkWidget *gtkArrow = QGtk::gtkWidget(arrowPath); + GtkWidget *gtkArrow = d->gtkWidget(arrowPath); gfloat scale = 0.7; gint minSize = 15; QRect arrowWidgetRect; - if (gtkArrow && !QGtk::gtk_check_version(2, 12, 0)) { - QGtk::gtk_widget_style_get(gtkArrow, "arrow-scaling", &scale, NULL); - QGtk::gtk_widget_style_get(gtkCombo, "arrow-size", &minSize, NULL); + if (gtkArrow && !d->gtk_check_version(2, 12, 0)) { + d->gtk_widget_style_get(gtkArrow, "arrow-scaling", &scale, NULL); + d->gtk_widget_style_get(gtkCombo, "arrow-size", &minSize, NULL); } if (gtkArrow) { arrowWidgetRect = QRect(gtkArrow->allocation.x, gtkArrow->allocation.y, @@ -1482,9 +1466,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom if (sunken) { int xoff, yoff; - GtkWidget *gtkButton = QGtk::gtkWidget(comboBoxPath + QLS(".GtkToggleButton")); - QGtk::gtk_widget_style_get(gtkButton, "child-displacement-x", &xoff, NULL); - QGtk::gtk_widget_style_get(gtkButton, "child-displacement-y", &yoff, NULL); + GtkWidget *gtkButton = d->gtkWidget(comboBoxPath + QLS(".GtkToggleButton")); + d->gtk_widget_style_get(gtkButton, "child-displacement-x", &xoff, NULL); + d->gtk_widget_style_get(gtkButton, "child-displacement-y", &yoff, NULL); arrowRect = arrowRect.adjusted(xoff, yoff, xoff, yoff); } @@ -1555,7 +1539,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom QStyleOptionToolButton label = *toolbutton; label.state = bflags; - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkToolButton.GtkButton")); QPalette pal = toolbutton->palette; if (option->state & State_Enabled && option->state & State_MouseOver && !(widget && widget->testAttribute(Qt::WA_SetPalette))) { @@ -1590,8 +1574,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom case CC_ScrollBar: if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { - GtkWidget *gtkHScrollBar = QGtk::gtkWidget(QLS("GtkHScrollbar")); - GtkWidget *gtkVScrollBar = QGtk::gtkWidget(QLS("GtkVScrollbar")); + GtkWidget *gtkHScrollBar = d->gtkWidget(QLS("GtkHScrollbar")); + GtkWidget *gtkVScrollBar = d->gtkWidget(QLS("GtkVScrollbar")); // Fill background in case the scrollbar is partially transparent painter->fillRect(option->rect, option->palette.background()); @@ -1608,8 +1592,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom gboolean trough_side_details = false; gboolean stepper_size = 14; gint trough_border = 1; - if (!QGtk::gtk_check_version(2, 10, 0)) { - QGtk::gtk_widget_style_get((GtkWidget*)(scrollbarWidget), + if (!d->gtk_check_version(2, 10, 0)) { + d->gtk_widget_style_get((GtkWidget*)(scrollbarWidget), "trough-border", &trough_border, "trough-side-details", &trough_side_details, "trough-under-steppers", &trough_under_steppers, @@ -1633,12 +1617,12 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom fakePos = maximum; else if (scrollBar->sliderPosition > scrollBar->minimum) fakePos = maximum - 1; - GtkObject *adjustment = QGtk::gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0); + GtkObject *adjustment = d->gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0); if (horizontal) - QGtk::gtk_range_set_adjustment((GtkRange*)(gtkHScrollBar), (GtkAdjustment*)(adjustment)); + d->gtk_range_set_adjustment((GtkRange*)(gtkHScrollBar), (GtkAdjustment*)(adjustment)); else - QGtk::gtk_range_set_adjustment((GtkRange*)(gtkVScrollBar), (GtkAdjustment*)(adjustment)); + d->gtk_range_set_adjustment((GtkRange*)(gtkVScrollBar), (GtkAdjustment*)(adjustment)); if (scrollBar->subControls & SC_ScrollBarGroove) { GtkStateType state = GTK_STATE_ACTIVE; @@ -1735,7 +1719,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom case CC_SpinBox: if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { - GtkWidget *gtkSpinButton = QGtk::gtkWidget(QLS("GtkSpinButton")); + GtkWidget *gtkSpinButton = d->gtkWidget(QLS("GtkSpinButton")); bool isEnabled = (spinBox->state & State_Enabled); bool hover = isEnabled && (spinBox->state & State_MouseOver); bool sunken = (spinBox->state & State_Sunken); @@ -1850,7 +1834,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom } } else { - int size = spinboxArrowSize(); + int size = d->getSpinboxArrowSize(); int w = size / 2 - 1; w -= w % 2 - 1; // force odd int h = (w + 1)/2; @@ -1882,8 +1866,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom case CC_Slider: if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { - GtkWidget *hScaleWidget = QGtk::gtkWidget(QLS("GtkHScale")); - GtkWidget *vScaleWidget = QGtk::gtkWidget(QLS("GtkVScale")); + GtkWidget *hScaleWidget = d->gtkWidget(QLS("GtkHScale")); + GtkWidget *vScaleWidget = d->gtkWidget(QLS("GtkVScale")); QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget); QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget); @@ -1907,16 +1891,16 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom style = scaleWidget->style; if ((option->subControls & SC_SliderGroove) && groove.isValid()) { - GtkObject *adjustment = QGtk::gtk_adjustment_new(slider->sliderPosition, + GtkObject *adjustment = d->gtk_adjustment_new(slider->sliderPosition, slider->minimum, slider->maximum, slider->singleStep, slider->singleStep, slider->pageStep); int outerSize; - QGtk::gtk_range_set_adjustment ((GtkRange*)(scaleWidget), (GtkAdjustment*)(adjustment)); - QGtk::gtk_range_set_inverted((GtkRange*)(scaleWidget), !horizontal); - QGtk::gtk_widget_style_get(scaleWidget, "trough-border", &outerSize, NULL); + d->gtk_range_set_adjustment ((GtkRange*)(scaleWidget), (GtkAdjustment*)(adjustment)); + d->gtk_range_set_inverted((GtkRange*)(scaleWidget), !horizontal); + d->gtk_widget_style_get(scaleWidget, "trough-border", &outerSize, NULL); outerSize++; GtkStateType state = gtkPainter.gtkState(option); @@ -1924,20 +1908,30 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom QRect grooveRect = option->rect.adjusted(focusFrameMargin, outerSize + focusFrameMargin, -focusFrameMargin, -outerSize - focusFrameMargin); - gtkPainter.paintBox( scaleWidget, "trough", grooveRect, state, - GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); - gboolean trough_side_details = false; // Indicates if the upper or lower scale background differs - if (!QGtk::gtk_check_version(2, 10, 0)) - QGtk::gtk_widget_style_get((GtkWidget*)(scaleWidget), "trough-side-details", &trough_side_details, NULL); + if (!d->gtk_check_version(2, 10, 0)) + d->gtk_widget_style_get((GtkWidget*)(scaleWidget), "trough-side-details", &trough_side_details, NULL); - if (trough_side_details && horizontal) { //### Vertical sliders look broken with this for some reason + if (!trough_side_details) { + gtkPainter.paintBox( scaleWidget, "trough", grooveRect, state, + GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); + } else { + QRect upperGroove = grooveRect; QRect lowerGroove = grooveRect; - lowerGroove.setRight(handle.center().x()); + + if (horizontal) { + upperGroove.setLeft(handle.center().x()); + lowerGroove.setRight(handle.center().x()); + } else { + upperGroove.setBottom(handle.center().y()); + lowerGroove.setTop(handle.center().y()); + } + + gtkPainter.paintBox( scaleWidget, "trough-upper", upperGroove, state, + GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); gtkPainter.paintBox( scaleWidget, "trough-lower", lowerGroove, state, GTK_SHADOW_IN, style, QString(QLS("p%0")).arg(slider->sliderPosition)); } - } if (option->subControls & SC_SliderTickmarks) { @@ -2050,18 +2044,20 @@ void QGtkStyle::drawControl(ControlElement element, QPainter *painter, const QWidget *widget) const { - if (!QGtk::isThemeAvailable()) { + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) { QCleanlooksStyle::drawControl(element, option, painter, widget); return; } - GtkStyle* style = QGtk::gtkStyle(); + GtkStyle* style = d->gtkStyle(); QGtkPainter gtkPainter(painter); switch (element) { case CE_ProgressBarLabel: if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { - GtkWidget *gtkProgressBar = QGtk::gtkWidget(QLS("GtkProgressBar")); + GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar")); if (!gtkProgressBar) return; @@ -2164,7 +2160,7 @@ void QGtkStyle::drawControl(ControlElement element, if (button->features & QStyleOptionButton::HasMenu) ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0); - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton")); QPalette pal = button->palette; int labelState = GTK_STATE_INSENSITIVE; if (option->state & State_Enabled) @@ -2185,7 +2181,7 @@ void QGtkStyle::drawControl(ControlElement element, bool isRadio = (element == CE_RadioButton); // Draw prelight background - GtkWidget *gtkRadioButton = QGtk::gtkWidget(QLS("GtkRadioButton")); + GtkWidget *gtkRadioButton = d->gtkWidget(QLS("GtkRadioButton")); if (option->state & State_MouseOver) { gtkPainter.paintFlatBox(gtkRadioButton, "checkbutton", option->rect, @@ -2253,7 +2249,7 @@ void QGtkStyle::drawControl(ControlElement element, } if (!cb->currentText.isEmpty() && !cb->editable) { - GtkWidget *gtkCombo = QGtk::gtkWidget(QLS("GtkComboBox")); + GtkWidget *gtkCombo = d->gtkWidget(QLS("GtkComboBox")); QPalette pal = cb->palette; int labelState = GTK_STATE_INSENSITIVE; @@ -2330,9 +2326,9 @@ void QGtkStyle::drawControl(ControlElement element, // Draws the header in tables. if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { Q_UNUSED(header); - GtkWidget *gtkTreeView = QGtk::gtkWidget(QLS("GtkTreeView")); + GtkWidget *gtkTreeView = d->gtkWidget(QLS("GtkTreeView")); // Get the middle column - GtkTreeViewColumn *column = QGtk::gtk_tree_view_get_column((GtkTreeView*)gtkTreeView, 1); + GtkTreeViewColumn *column = d->gtk_tree_view_get_column((GtkTreeView*)gtkTreeView, 1); Q_ASSERT(column); GtkWidget *gtkTreeHeader = column->button; @@ -2351,7 +2347,7 @@ void QGtkStyle::drawControl(ControlElement element, #ifndef QT_NO_SIZEGRIP case CE_SizeGrip: { - GtkWidget *gtkStatusbar = QGtk::gtkWidget(QLS("GtkStatusbar.GtkFrame")); + GtkWidget *gtkStatusbar = d->gtkWidget(QLS("GtkStatusbar.GtkFrame")); QRect gripRect = option->rect.adjusted(0, 0, -gtkStatusbar->style->xthickness, -gtkStatusbar->style->ythickness); gtkPainter.paintResizeGrip( gtkStatusbar, "statusbar", gripRect, GTK_STATE_NORMAL, GTK_SHADOW_OUT, QApplication::isRightToLeft() ? @@ -2363,7 +2359,7 @@ void QGtkStyle::drawControl(ControlElement element, #endif // QT_NO_SIZEGRIP case CE_MenuBarEmptyArea: { - GtkWidget *gtkMenubar = QGtk::gtkWidget(QLS("GtkMenuBar")); + GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar")); GdkColor gdkBg = gtkMenubar->style->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8)); if (widget) { // See CE_MenuBarItem @@ -2373,7 +2369,7 @@ void QGtkStyle::drawControl(ControlElement element, QPainter pmPainter(&pixmap); QGtkPainter gtkMenuBarPainter(&pmPainter); GtkShadowType shadow_type; - QGtk::gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL); + d->gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL); gtkMenuBarPainter.paintBox( gtkMenubar, "menubar", menuBarRect, GTK_STATE_NORMAL, shadow_type, gtkMenubar->style); pmPainter.end(); @@ -2386,8 +2382,8 @@ void QGtkStyle::drawControl(ControlElement element, painter->save(); if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { - GtkWidget *gtkMenubarItem = QGtk::gtkWidget(QLS("GtkMenuBar.GtkMenuItem")); - GtkWidget *gtkMenubar = QGtk::gtkWidget(QLS("GtkMenuBar")); + GtkWidget *gtkMenubarItem = d->gtkWidget(QLS("GtkMenuBar.GtkMenuItem")); + GtkWidget *gtkMenubar = d->gtkWidget(QLS("GtkMenuBar")); style = gtkMenubarItem->style; @@ -2402,7 +2398,7 @@ void QGtkStyle::drawControl(ControlElement element, QPainter pmPainter(&pixmap); QGtkPainter menubarPainter(&pmPainter); GtkShadowType shadow_type; - QGtk::gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL); + d->gtk_widget_style_get(gtkMenubar, "shadow-type", &shadow_type, NULL); GdkColor gdkBg = gtkMenubar->style->bg[GTK_STATE_NORMAL]; // Theme can depend on transparency painter->fillRect(option->rect, QColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8)); menubarPainter.paintBox(gtkMenubar, "menubar", menuBarRect, @@ -2426,7 +2422,7 @@ void QGtkStyle::drawControl(ControlElement element, if (act) { GtkShadowType shadowType = GTK_SHADOW_NONE; - QGtk::gtk_widget_style_get (gtkMenubarItem, "selected-shadow-type", &shadowType, NULL); + d->gtk_widget_style_get (gtkMenubarItem, "selected-shadow-type", &shadowType, NULL); gtkPainter.paintBox(gtkMenubarItem, "menuitem", option->rect.adjusted(0, 0, 0, 3), GTK_STATE_PRELIGHT, shadowType, gtkMenubarItem->style); //draw text @@ -2443,7 +2439,7 @@ void QGtkStyle::drawControl(ControlElement element, break; case CE_Splitter: { - GtkWidget *gtkWindow = QGtk::gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed + GtkWidget *gtkWindow = d->gtkWidget(QLS("GtkWindow")); // The Murrine Engine currently assumes a widget is passed gtkPainter.paintHandle(gtkWindow, "splitter", option->rect, gtkPainter.gtkState(option), GTK_SHADOW_NONE, !(option->state & State_Horizontal) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, style); @@ -2463,9 +2459,9 @@ void QGtkStyle::drawControl(ControlElement element, if (toolbar->positionWithinLine != QStyleOptionToolBar::End) rect.adjust(0, 0, 1, 0); - GtkWidget *gtkToolbar = QGtk::gtkWidget(QLS("GtkToolbar")); + GtkWidget *gtkToolbar = d->gtkWidget(QLS("GtkToolbar")); GtkShadowType shadow_type = GTK_SHADOW_NONE; - QGtk::gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL); + d->gtk_widget_style_get(gtkToolbar, "shadow-type", &shadow_type, NULL); gtkPainter.paintBox( gtkToolbar, "toolbar", rect, GTK_STATE_NORMAL, shadow_type, gtkToolbar->style); } @@ -2482,22 +2478,22 @@ void QGtkStyle::drawControl(ControlElement element, const int windowsItemHMargin = 3; // menu item hor text margin const int windowsItemVMargin = 26; // menu item ver text margin const int windowsRightBorder = 15; // right border on windows - GtkWidget *gtkMenu = QGtk::gtkWidget(QLS("GtkMenu")); - GtkWidget *gtkMenuItem = menuItem->checked ? QGtk::gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")) : - QGtk::gtkWidget(QLS("GtkMenu.GtkMenuItem")); + GtkWidget *gtkMenu = d->gtkWidget(QLS("GtkMenu")); + GtkWidget *gtkMenuItem = menuItem->checked ? d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")) : + d->gtkWidget(QLS("GtkMenu.GtkMenuItem")); style = gtkPainter.getStyle(gtkMenuItem); QColor borderColor = option->palette.background().color().darker(160); QColor shadow = option->palette.dark().color(); if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { - GtkWidget *gtkMenuSeparator = QGtk::gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem")); + GtkWidget *gtkMenuSeparator = d->gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem")); painter->setPen(shadow.lighter(106)); gboolean wide_separators = 0; gint separator_height = 0; guint horizontal_padding = 3; - if (!QGtk::gtk_check_version(2, 10, 0)) { - QGtk::gtk_widget_style_get(gtkMenuSeparator, + if (!d->gtk_check_version(2, 10, 0)) { + d->gtk_widget_style_get(gtkMenuSeparator, "wide-separators", &wide_separators, "separator-height", &separator_height, "horizontal-padding", &horizontal_padding, @@ -2531,7 +2527,7 @@ void QGtkStyle::drawControl(ControlElement element, bool ignoreCheckMark = false; gint checkSize; - QGtk::gtk_widget_style_get(QGtk::gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL); + d->gtk_widget_style_get(d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL); int checkcol = qMax(menuItem->maxIconWidth, qMax(20, checkSize)); @@ -2718,7 +2714,7 @@ void QGtkStyle::drawControl(ControlElement element, // "arrow-scaling" is actually hardcoded and fails on hardy (see gtk+-2.12/gtkmenuitem.c) // though the current documentation states otherwise int horizontal_padding; - QGtk::gtk_widget_style_get(gtkMenuItem, "horizontal-padding", &horizontal_padding, NULL); + d->gtk_widget_style_get(gtkMenuItem, "horizontal-padding", &horizontal_padding, NULL); const int dim = static_cast<int>(arrow_size * arrow_scaling); int xpos = menuItem->rect.left() + menuItem->rect.width() - horizontal_padding - dim; @@ -2736,12 +2732,12 @@ void QGtkStyle::drawControl(ControlElement element, case CE_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton")); proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget); QStyleOptionButton subopt = *btn; subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); gint interiorFocus = true; - QGtk::gtk_widget_style_get(gtkButton, "interior-focus", &interiorFocus, NULL); + d->gtk_widget_style_get(gtkButton, "interior-focus", &interiorFocus, NULL); int xt = interiorFocus ? gtkButton->style->xthickness : 0; int yt = interiorFocus ? gtkButton->style->ythickness : 0; @@ -2762,7 +2758,7 @@ void QGtkStyle::drawControl(ControlElement element, case CE_TabBarTabShape: if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) { - GtkWidget *gtkNotebook = QGtk::gtkWidget(QLS("GtkNotebook")); + GtkWidget *gtkNotebook = d->gtkWidget(QLS("GtkNotebook")); style = gtkPainter.getStyle(gtkNotebook); QRect rect = option->rect; @@ -2829,7 +2825,7 @@ void QGtkStyle::drawControl(ControlElement element, case CE_ProgressBarGroove: if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { Q_UNUSED(bar); - GtkWidget *gtkProgressBar = QGtk::gtkWidget(QLS("GtkProgressBar")); + GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar")); GtkStateType state = gtkPainter.gtkState(option); gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, gtkProgressBar->style); } @@ -2839,7 +2835,7 @@ void QGtkStyle::drawControl(ControlElement element, case CE_ProgressBarContents: if (const QStyleOptionProgressBar *bar = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { GtkStateType state = option->state & State_Enabled ? GTK_STATE_NORMAL : GTK_STATE_INSENSITIVE; - GtkWidget *gtkProgressBar = QGtk::gtkWidget(QLS("GtkProgressBar")); + GtkWidget *gtkProgressBar = d->gtkWidget(QLS("GtkProgressBar")); style = gtkProgressBar->style; gtkPainter.paintBox( gtkProgressBar, "trough", option->rect, state, GTK_SHADOW_IN, style); int xt = style->xthickness; @@ -2887,8 +2883,8 @@ void QGtkStyle::drawControl(ControlElement element, else if (bar->progress > bar->minimum) fakePos = maximum - 1; - GtkObject *adjustment = QGtk::gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0); - QGtk::gtk_progress_set_adjustment((GtkProgress*)(gtkProgressBar), (GtkAdjustment*)(adjustment)); + GtkObject *adjustment = d->gtk_adjustment_new(fakePos, 0, maximum, 0, 0, 0); + d->gtk_progress_set_adjustment((GtkProgress*)(gtkProgressBar), (GtkAdjustment*)(adjustment)); QRect progressBar; @@ -2928,8 +2924,10 @@ void QGtkStyle::drawControl(ControlElement element, QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const { + Q_D(const QGtkStyle); + QRect rect = QWindowsStyle::subControlRect(control, option, subControl, widget); - if (!QGtk::isThemeAvailable()) + if (!d->isThemeAvailable()) return QCleanlooksStyle::subControlRect(control, option, subControl, widget); switch (control) { @@ -2995,7 +2993,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple case CC_SpinBox: if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { - GtkWidget *gtkSpinButton = QGtk::gtkWidget(QLS("GtkSpinButton")); + GtkWidget *gtkSpinButton = d->gtkWidget(QLS("GtkSpinButton")); int center = spinbox->rect.height() / 2; int xt = spinbox->frame ? gtkSpinButton->style->xthickness : 0; int yt = spinbox->frame ? gtkSpinButton->style->ythickness : 0; @@ -3003,7 +3001,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple QSize bs; bs.setHeight(qMax(8, spinbox->rect.height()/2 - y)); - bs.setWidth(spinboxArrowSize()); + bs.setWidth(d->getSpinboxArrowSize()); int x, lx, rx; x = spinbox->rect.width() - y - bs.width() + 2; lx = xt; @@ -3049,17 +3047,17 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { // We employ the gtk widget to position arrows and separators for us QString comboBoxPath = box->editable ? QLS("GtkComboBoxEntry") : QLS("GtkComboBox"); - GtkWidget *gtkCombo = QGtk::gtkWidget(comboBoxPath); - QGtk::gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); + GtkWidget *gtkCombo = d->gtkWidget(comboBoxPath); + d->gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR); GtkAllocation geometry = {0, 0, qMax(0, option->rect.width()), qMax(0, option->rect.height())}; - QGtk::gtk_widget_size_allocate(gtkCombo, &geometry); + d->gtk_widget_size_allocate(gtkCombo, &geometry); int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, option, widget); QString arrowPath = comboBoxPath + QLS(".GtkToggleButton"); if (!box->editable && !appears_as_list) arrowPath += QLS(".GtkHBox.GtkArrow"); - GtkWidget *arrowWidget = QGtk::gtkWidget(arrowPath); + GtkWidget *arrowWidget = d->gtkWidget(arrowPath); if (!arrowWidget) return QCleanlooksStyle::subControlRect(control, option, subControl, widget); @@ -3104,19 +3102,19 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple \reimp */ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, - const QSize &size, const QWidget *widget) const { + Q_D(const QGtkStyle); QSize newSize = QCleanlooksStyle::sizeFromContents(type, option, size, widget); - if (!QGtk::isThemeAvailable()) + if (!d->isThemeAvailable()) return newSize; switch (type) { case CT_ToolButton: if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkToolButton.GtkButton")); newSize = size + QSize(2 * gtkButton->style->xthickness, 1 + 2 * gtkButton->style->ythickness); if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) { QSize minSize(0, 25); @@ -3124,7 +3122,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, minSize = toolbutton->iconSize + QSize(12, 12); newSize = newSize.expandedTo(minSize); } - + if (toolbutton->features & QStyleOptionToolButton::HasMenu) newSize += QSize(6, 0); } @@ -3135,10 +3133,10 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, int textMargin = 8; if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) { - GtkWidget *gtkMenuSeparator = QGtk::gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem")); + GtkWidget *gtkMenuSeparator = d->gtkWidget(QLS("GtkMenu.GtkSeparatorMenuItem")); gboolean wide_separators; gint separator_height; - QGtk::gtk_widget_style_get(gtkMenuSeparator, + d->gtk_widget_style_get(gtkMenuSeparator, "wide-separators", &wide_separators, "separator-height", &separator_height, NULL); @@ -3147,14 +3145,14 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, break; } - GtkWidget *gtkMenuItem = QGtk::gtkWidget(QLS("GtkMenu.GtkMenuItem")); + GtkWidget *gtkMenuItem = d->gtkWidget(QLS("GtkMenu.GtkMenuItem")); GtkStyle* style = gtkMenuItem->style; newSize += QSize(textMargin + style->xthickness - 2, style->ythickness - 4); // Cleanlooks assumes a check column of 20 pixels so we need to // expand it a bit gint checkSize; - QGtk::gtk_widget_style_get(QGtk::gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL); + d->gtk_widget_style_get(d->gtkWidget(QLS("GtkMenu.GtkCheckMenuItem")), "indicator-size", &checkSize, NULL); newSize.setHeight(qMax(newSize.height(), checkSize + 2)); newSize.setWidth(newSize.width() + qMax(0, checkSize - 20)); } @@ -3169,22 +3167,22 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, case CT_SpinBox: // QSpinBox does some nasty things that depends on CT_LineEdit - newSize = size + QSize(0, -QGtk::gtkWidget(QLS("GtkSpinButton"))->style->ythickness * 2 + 2); + newSize = size + QSize(0, -d->gtkWidget(QLS("GtkSpinButton"))->style->ythickness * 2 + 2); break; case CT_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { - GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton")); + GtkWidget *gtkButton = d->gtkWidget(QLS("GtkButton")); gint focusPadding, focusWidth; - QGtk::gtk_widget_style_get(gtkButton, "focus-padding", &focusPadding, NULL); - QGtk::gtk_widget_style_get(gtkButton, "focus-line-width", &focusWidth, NULL); + d->gtk_widget_style_get(gtkButton, "focus-padding", &focusPadding, NULL); + d->gtk_widget_style_get(gtkButton, "focus-line-width", &focusWidth, NULL); newSize = size; newSize += QSize(2*gtkButton->style->xthickness + 4, 2*gtkButton->style->ythickness); newSize += QSize(2*(focusWidth + focusPadding + 2), 2*(focusWidth + focusPadding)); - GtkWidget *gtkButtonBox = QGtk::gtkWidget(QLS("GtkHButtonBox")); + GtkWidget *gtkButtonBox = d->gtkWidget(QLS("GtkHButtonBox")); gint minWidth = 85, minHeight = 0; - QGtk::gtk_widget_style_get(gtkButtonBox, "child-min-width", &minWidth, + d->gtk_widget_style_get(gtkButtonBox, "child-min-width", &minWidth, "child-min-height", &minHeight, NULL); if (!btn->text.isEmpty() && newSize.width() < minWidth) newSize.setWidth(minWidth); @@ -3195,7 +3193,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, break; case CT_Slider: { - GtkWidget *gtkSlider = QGtk::gtkWidget(QLS("GtkHScale")); + GtkWidget *gtkSlider = d->gtkWidget(QLS("GtkHScale")); newSize = size + QSize(2*gtkSlider->style->xthickness, 2*gtkSlider->style->ythickness); } break; @@ -3205,7 +3203,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, break; case CT_LineEdit: { - GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry")); + GtkWidget *gtkEntry = d->gtkWidget(QLS("GtkEntry")); newSize = size + QSize(2*gtkEntry->style->xthickness, 2*gtkEntry->style->ythickness); } break; @@ -3216,7 +3214,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, case CT_ComboBox: if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { - GtkWidget *gtkCombo = QGtk::gtkWidget(QLS("GtkComboBox")); + GtkWidget *gtkCombo = d->gtkWidget(QLS("GtkComboBox")); QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget); newSize = size + QSize(12 + arrowButtonRect.width() + 2*gtkCombo->style->xthickness, 4 + 2*gtkCombo->style->ythickness); @@ -3249,7 +3247,9 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option, QPixmap QGtkStyle::standardPixmap(StandardPixmap sp, const QStyleOption *option, const QWidget *widget) const { - if (!QGtk::isThemeAvailable()) + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) return QCleanlooksStyle::standardPixmap(sp, option, widget); QPixmap pixmap; @@ -3316,7 +3316,9 @@ QIcon QGtkStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { - if (!QGtk::isThemeAvailable()) + Q_D(const QGtkStyle); + + if (!d->isThemeAvailable()) return QCleanlooksStyle::standardIconImplementation(standardIcon, option, widget); switch (standardIcon) { case SP_DialogDiscardButton: diff --git a/src/gui/styles/qgtkstyle.h b/src/gui/styles/qgtkstyle.h index 20c2b52..5c3bad1 100644 --- a/src/gui/styles/qgtkstyle.h +++ b/src/gui/styles/qgtkstyle.h @@ -45,6 +45,7 @@ #include <QtGui/QCleanlooksStyle> #include <QtGui/QPalette> #include <QtGui/QFont> +#include <QtGui/QFileDialog> QT_BEGIN_HEADER @@ -64,6 +65,8 @@ class Q_GUI_EXPORT QGtkStyle : public QCleanlooksStyle public: QGtkStyle(); + QGtkStyle(QGtkStylePrivate &dd); + ~QGtkStyle(); QPalette standardPalette() const; @@ -107,12 +110,15 @@ public: void unpolish(QWidget *widget); void unpolish(QApplication *app); + static bool getGConfBool(const QString &key, bool fallback = 0); + static QString getGConfString(const QString &key, const QString &fallback = QString()); + + protected Q_SLOTS: QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget = 0) const; }; - #endif //!defined(QT_NO_STYLE_QGTK) QT_END_NAMESPACE diff --git a/src/gui/styles/qgtkstyle_p.cpp b/src/gui/styles/qgtkstyle_p.cpp new file mode 100644 index 0000000..7119a4f --- /dev/null +++ b/src/gui/styles/qgtkstyle_p.cpp @@ -0,0 +1,1069 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgtkstyle_p.h" + +// This file is responsible for resolving all GTK functions we use +// dynamically. This is done to avoid link-time dependancy on GTK +// as well as crashes occurring due to usage of the GTK_QT engines +// +// Additionally we create a map of common GTK widgets that we can pass +// to the GTK theme engine as many engines resort to querying the +// actual widget pointers for details that are not covered by the +// state flags + +#include <QtCore/qglobal.h> +#if !defined(QT_NO_STYLE_GTK) + +#include <QtCore/QEvent> +#include <QtCore/QFile> +#include <QtCore/QStringList> +#include <QtCore/QTextStream> +#include <QtCore/QHash> +#include <QtCore/QUrl> +#include <QtCore/QLibrary> + +#include <private/qapplication_p.h> +#include <private/qiconloader_p.h> + +#include <QtGui/QMenu> +#include <QtGui/QStyle> +#include <QtGui/QApplication> +#include <QtGui/QPixmapCache> +#include <QtGui/QStatusBar> +#include <QtGui/QMenuBar> +#include <QtGui/QToolBar> +#include <QtGui/QToolButton> +#include <QtGui/QX11Info> + +#include <private/qt_x11_p.h> + +QT_BEGIN_NAMESPACE + +static bool displayDepth = -1; +Q_GLOBAL_STATIC(QGtkStyleUpdateScheduler, styleScheduler) + +Ptr_gtk_container_forall QGtkStylePrivate::gtk_container_forall = 0; +Ptr_gtk_init QGtkStylePrivate::gtk_init = 0; +Ptr_gtk_style_attach QGtkStylePrivate::gtk_style_attach = 0; +Ptr_gtk_window_new QGtkStylePrivate::gtk_window_new = 0; +Ptr_gtk_widget_destroy QGtkStylePrivate::gtk_widget_destroy = 0; +Ptr_gtk_widget_realize QGtkStylePrivate::gtk_widget_realize = 0; +Ptr_gtk_widget_set_default_direction QGtkStylePrivate::gtk_widget_set_default_direction = 0; +Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_fg = 0; +Ptr_gtk_widget_modify_color QGtkStylePrivate::gtk_widget_modify_bg = 0; +Ptr_gtk_arrow_new QGtkStylePrivate::gtk_arrow_new = 0; +Ptr_gtk_menu_item_new QGtkStylePrivate::gtk_menu_item_new = 0; +Ptr_gtk_check_menu_item_new QGtkStylePrivate::gtk_check_menu_item_new = 0; +Ptr_gtk_menu_bar_new QGtkStylePrivate::gtk_menu_bar_new = 0; +Ptr_gtk_menu_new QGtkStylePrivate::gtk_menu_new = 0; +Ptr_gtk_button_new QGtkStylePrivate::gtk_button_new = 0; +Ptr_gtk_tool_button_new QGtkStylePrivate::gtk_tool_button_new = 0; +Ptr_gtk_hbutton_box_new QGtkStylePrivate::gtk_hbutton_box_new = 0; +Ptr_gtk_check_button_new QGtkStylePrivate::gtk_check_button_new = 0; +Ptr_gtk_radio_button_new QGtkStylePrivate::gtk_radio_button_new = 0; +Ptr_gtk_spin_button_new QGtkStylePrivate::gtk_spin_button_new = 0; +Ptr_gtk_frame_new QGtkStylePrivate::gtk_frame_new = 0; +Ptr_gtk_expander_new QGtkStylePrivate::gtk_expander_new = 0; +Ptr_gtk_statusbar_new QGtkStylePrivate::gtk_statusbar_new = 0; +Ptr_gtk_entry_new QGtkStylePrivate::gtk_entry_new = 0; +Ptr_gtk_hscale_new QGtkStylePrivate::gtk_hscale_new = 0; +Ptr_gtk_vscale_new QGtkStylePrivate::gtk_vscale_new = 0; +Ptr_gtk_hscrollbar_new QGtkStylePrivate::gtk_hscrollbar_new = 0; +Ptr_gtk_vscrollbar_new QGtkStylePrivate::gtk_vscrollbar_new = 0; +Ptr_gtk_scrolled_window_new QGtkStylePrivate::gtk_scrolled_window_new = 0; +Ptr_gtk_notebook_new QGtkStylePrivate::gtk_notebook_new = 0; +Ptr_gtk_toolbar_new QGtkStylePrivate::gtk_toolbar_new = 0; +Ptr_gtk_toolbar_insert QGtkStylePrivate::gtk_toolbar_insert = 0; +Ptr_gtk_separator_tool_item_new QGtkStylePrivate::gtk_separator_tool_item_new = 0; +Ptr_gtk_tree_view_new QGtkStylePrivate::gtk_tree_view_new = 0; +Ptr_gtk_combo_box_new QGtkStylePrivate::gtk_combo_box_new = 0; +Ptr_gtk_combo_box_entry_new QGtkStylePrivate::gtk_combo_box_entry_new = 0; +Ptr_gtk_progress_bar_new QGtkStylePrivate::gtk_progress_bar_new = 0; +Ptr_gtk_container_add QGtkStylePrivate::gtk_container_add = 0; +Ptr_gtk_menu_shell_append QGtkStylePrivate::gtk_menu_shell_append = 0; +Ptr_gtk_progress_set_adjustment QGtkStylePrivate::gtk_progress_set_adjustment = 0; +Ptr_gtk_range_set_adjustment QGtkStylePrivate::gtk_range_set_adjustment = 0; +Ptr_gtk_range_set_inverted QGtkStylePrivate::gtk_range_set_inverted = 0; +Ptr_gtk_icon_factory_lookup_default QGtkStylePrivate::gtk_icon_factory_lookup_default = 0; +Ptr_gtk_icon_theme_get_default QGtkStylePrivate::gtk_icon_theme_get_default = 0; +Ptr_gtk_widget_style_get QGtkStylePrivate::gtk_widget_style_get = 0; +Ptr_gtk_icon_set_render_icon QGtkStylePrivate::gtk_icon_set_render_icon = 0; +Ptr_gtk_fixed_new QGtkStylePrivate::gtk_fixed_new = 0; +Ptr_gtk_tree_view_column_new QGtkStylePrivate::gtk_tree_view_column_new = 0; +Ptr_gtk_tree_view_get_column QGtkStylePrivate::gtk_tree_view_get_column = 0; +Ptr_gtk_tree_view_append_column QGtkStylePrivate::gtk_tree_view_append_column = 0; +Ptr_gtk_paint_check QGtkStylePrivate::gtk_paint_check = 0; +Ptr_gtk_paint_box QGtkStylePrivate::gtk_paint_box = 0; +Ptr_gtk_paint_box_gap QGtkStylePrivate::gtk_paint_box_gap = 0; +Ptr_gtk_paint_flat_box QGtkStylePrivate::gtk_paint_flat_box = 0; +Ptr_gtk_paint_option QGtkStylePrivate::gtk_paint_option = 0; +Ptr_gtk_paint_extension QGtkStylePrivate::gtk_paint_extension = 0; +Ptr_gtk_paint_slider QGtkStylePrivate::gtk_paint_slider = 0; +Ptr_gtk_paint_shadow QGtkStylePrivate::gtk_paint_shadow = 0; +Ptr_gtk_paint_resize_grip QGtkStylePrivate::gtk_paint_resize_grip = 0; +Ptr_gtk_paint_focus QGtkStylePrivate::gtk_paint_focus = 0; +Ptr_gtk_paint_arrow QGtkStylePrivate::gtk_paint_arrow = 0; +Ptr_gtk_paint_handle QGtkStylePrivate::gtk_paint_handle = 0; +Ptr_gtk_paint_expander QGtkStylePrivate::gtk_paint_expander = 0; +Ptr_gtk_adjustment_new QGtkStylePrivate::gtk_adjustment_new = 0; +Ptr_gtk_paint_hline QGtkStylePrivate::gtk_paint_hline = 0; +Ptr_gtk_paint_vline QGtkStylePrivate::gtk_paint_vline = 0; +Ptr_gtk_menu_item_set_submenu QGtkStylePrivate::gtk_menu_item_set_submenu = 0; +Ptr_gtk_settings_get_default QGtkStylePrivate::gtk_settings_get_default = 0; +Ptr_gtk_separator_menu_item_new QGtkStylePrivate::gtk_separator_menu_item_new = 0; +Ptr_gtk_widget_size_allocate QGtkStylePrivate::gtk_widget_size_allocate = 0; +Ptr_gtk_widget_set_direction QGtkStylePrivate::gtk_widget_set_direction = 0; +Ptr_gtk_widget_path QGtkStylePrivate::gtk_widget_path = 0; +Ptr_gtk_container_get_type QGtkStylePrivate::gtk_container_get_type = 0; +Ptr_gtk_window_get_type QGtkStylePrivate::gtk_window_get_type = 0; +Ptr_gtk_widget_get_type QGtkStylePrivate::gtk_widget_get_type = 0; +Ptr_gtk_rc_get_style_by_paths QGtkStylePrivate::gtk_rc_get_style_by_paths = 0; +Ptr_gtk_check_version QGtkStylePrivate::gtk_check_version = 0; + +Ptr_pango_font_description_get_size QGtkStylePrivate::pango_font_description_get_size = 0; +Ptr_pango_font_description_get_weight QGtkStylePrivate::pango_font_description_get_weight = 0; +Ptr_pango_font_description_get_family QGtkStylePrivate::pango_font_description_get_family = 0; +Ptr_pango_font_description_get_style QGtkStylePrivate::pango_font_description_get_style = 0; + +Ptr_gtk_file_filter_new QGtkStylePrivate::gtk_file_filter_new = 0; +Ptr_gtk_file_filter_set_name QGtkStylePrivate::gtk_file_filter_set_name = 0; +Ptr_gtk_file_filter_add_pattern QGtkStylePrivate::gtk_file_filter_add_pattern = 0; +Ptr_gtk_file_chooser_add_filter QGtkStylePrivate::gtk_file_chooser_add_filter = 0; +Ptr_gtk_file_chooser_set_filter QGtkStylePrivate::gtk_file_chooser_set_filter = 0; +Ptr_gtk_file_chooser_get_filter QGtkStylePrivate::gtk_file_chooser_get_filter = 0; +Ptr_gtk_file_chooser_dialog_new QGtkStylePrivate::gtk_file_chooser_dialog_new = 0; +Ptr_gtk_file_chooser_set_current_folder QGtkStylePrivate::gtk_file_chooser_set_current_folder = 0; +Ptr_gtk_file_chooser_get_filename QGtkStylePrivate::gtk_file_chooser_get_filename = 0; +Ptr_gtk_file_chooser_get_filenames QGtkStylePrivate::gtk_file_chooser_get_filenames = 0; +Ptr_gtk_file_chooser_set_current_name QGtkStylePrivate::gtk_file_chooser_set_current_name = 0; +Ptr_gtk_dialog_run QGtkStylePrivate::gtk_dialog_run = 0; +Ptr_gtk_file_chooser_set_filename QGtkStylePrivate::gtk_file_chooser_set_filename = 0; + +Ptr_gdk_pixbuf_get_pixels QGtkStylePrivate::gdk_pixbuf_get_pixels = 0; +Ptr_gdk_pixbuf_get_width QGtkStylePrivate::gdk_pixbuf_get_width = 0; +Ptr_gdk_pixbuf_get_height QGtkStylePrivate::gdk_pixbuf_get_height = 0; +Ptr_gdk_pixmap_new QGtkStylePrivate::gdk_pixmap_new = 0; +Ptr_gdk_pixbuf_new QGtkStylePrivate::gdk_pixbuf_new = 0; +Ptr_gdk_pixbuf_get_from_drawable QGtkStylePrivate::gdk_pixbuf_get_from_drawable = 0; +Ptr_gdk_draw_rectangle QGtkStylePrivate::gdk_draw_rectangle = 0; +Ptr_gdk_pixbuf_unref QGtkStylePrivate::gdk_pixbuf_unref = 0; +Ptr_gdk_drawable_unref QGtkStylePrivate::gdk_drawable_unref = 0; +Ptr_gdk_drawable_get_depth QGtkStylePrivate::gdk_drawable_get_depth = 0; +Ptr_gdk_color_free QGtkStylePrivate::gdk_color_free = 0; +Ptr_gdk_x11_window_set_user_time QGtkStylePrivate::gdk_x11_window_set_user_time = 0; +Ptr_gdk_x11_drawable_get_xid QGtkStylePrivate::gdk_x11_drawable_get_xid = 0; +Ptr_gdk_x11_drawable_get_xdisplay QGtkStylePrivate::gdk_x11_drawable_get_xdisplay = 0; + +Ptr_gconf_client_get_default QGtkStylePrivate::gconf_client_get_default = 0; +Ptr_gconf_client_get_string QGtkStylePrivate::gconf_client_get_string = 0; +Ptr_gconf_client_get_bool QGtkStylePrivate::gconf_client_get_bool = 0; + +Ptr_gnome_icon_lookup_sync QGtkStylePrivate::gnome_icon_lookup_sync = 0; +Ptr_gnome_vfs_init QGtkStylePrivate::gnome_vfs_init = 0; + +typedef int (*x11ErrorHandler)(Display*, XErrorEvent*); + +static void gtkStyleSetCallback(GtkWidget*, QGtkStylePrivate* stylePrivate) +{ + // We have to let this function return and complete the event + // loop to ensure that all gtk widgets have been styled before + // updating + QMetaObject::invokeMethod(styleScheduler(), "updateTheme", Qt::QueuedConnection, Q_ARG(QGtkStylePrivate*, stylePrivate)); +} + +static void update_toolbar_style(GtkWidget *gtkToolBar, GParamSpec *, gpointer) +{ + GtkToolbarStyle toolbar_style = GTK_TOOLBAR_ICONS; + g_object_get(gtkToolBar, "toolbar-style", &toolbar_style, NULL); + QWidgetList widgets = QApplication::allWidgets(); + for (int i = 0; i < widgets.size(); ++i) { + QWidget *widget = widgets.at(i); + if (qobject_cast<QToolButton*>(widget)) { + QEvent event(QEvent::StyleChange); + QApplication::sendEvent(widget, &event); + } + } +} + +static QString classPath(GtkWidget *widget) +{ + char* class_path; + QGtkStylePrivate::gtk_widget_path (widget, NULL, &class_path, NULL); + QString path = QLS(class_path); + g_free(class_path); + + // Remove the prefixes + path.remove(QLS("GtkWindow.")); + path.remove(QLS("GtkFixed.")); + return path; +} + + + +bool QGtkStyleFilter::eventFilter(QObject *obj, QEvent *e) +{ + if (e->type() == QEvent::ApplicationPaletteChange) { + // Only do this the first time since this will also + // generate applicationPaletteChange events + if (!qt_app_palettes_hash() || qt_app_palettes_hash()->isEmpty()) { + stylePrivate->applyCustomPaletteHash(); + } + } + return QObject::eventFilter(obj, e); +} + +QGtkStylePrivate::QGtkStylePrivate() + : QCleanlooksStylePrivate() + , filter(this) +{ +} + +void QGtkStylePrivate::init() +{ + resolveGtk(); + initGtkWidgets(); + if (isThemeAvailable()) + qApp->installEventFilter(&filter); +} + +GtkWidget* QGtkStylePrivate::gtkWidget(const QString &path) +{ + GtkWidget *widget = gtkWidgetMap()->value(path); + if (!widget) { + // Theme might have rearranged widget internals + widget = gtkWidgetMap()->value(path); + } + return widget; +} + +GtkStyle* QGtkStylePrivate::gtkStyle(const QString &path) +{ + if (gtkWidgetMap()->contains(path)) + return gtkWidgetMap()->value(path)->style; + return 0; +} + +/*! \internal + * Get references to gtk functions after we dynamically load the library. + */ +void QGtkStylePrivate::resolveGtk() +{ + // enforce the "0" suffix, so we'll open libgtk-x11-2.0.so.0 + QLibrary libgtk(QLS("gtk-x11-2.0"), 0, 0); + + gtk_init = (Ptr_gtk_init)libgtk.resolve("gtk_init"); + gtk_window_new = (Ptr_gtk_window_new)libgtk.resolve("gtk_window_new"); + gtk_style_attach = (Ptr_gtk_style_attach)libgtk.resolve("gtk_style_attach"); + gtk_widget_destroy = (Ptr_gtk_widget_destroy)libgtk.resolve("gtk_widget_destroy"); + gtk_widget_realize = (Ptr_gtk_widget_realize)libgtk.resolve("gtk_widget_realize"); + + gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); + gtk_file_filter_new = (Ptr_gtk_file_filter_new)libgtk.resolve("gtk_file_filter_new"); + gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)libgtk.resolve("gtk_file_filter_set_name"); + gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)libgtk.resolve("gtk_file_filter_add_pattern"); + gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)libgtk.resolve("gtk_file_chooser_add_filter"); + gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)libgtk.resolve("gtk_file_chooser_set_filter"); + gtk_file_chooser_get_filter = (Ptr_gtk_file_chooser_get_filter)libgtk.resolve("gtk_file_chooser_get_filter"); + gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)libgtk.resolve("gtk_file_chooser_dialog_new"); + gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder"); + gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)libgtk.resolve("gtk_file_chooser_get_filename"); + gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)libgtk.resolve("gtk_file_chooser_get_filenames"); + gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)libgtk.resolve("gtk_file_chooser_set_current_name"); + gtk_dialog_run = (Ptr_gtk_dialog_run)libgtk.resolve("gtk_dialog_run"); + gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)libgtk.resolve("gtk_file_chooser_set_filename"); + + gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)libgtk.resolve("gdk_pixbuf_get_pixels"); + gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)libgtk.resolve("gdk_pixbuf_get_width"); + gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)libgtk.resolve("gdk_pixbuf_get_height"); + gdk_pixmap_new = (Ptr_gdk_pixmap_new)libgtk.resolve("gdk_pixmap_new"); + gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)libgtk.resolve("gdk_pixbuf_new"); + gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)libgtk.resolve("gdk_pixbuf_get_from_drawable"); + gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)libgtk.resolve("gdk_draw_rectangle"); + gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)libgtk.resolve("gdk_pixbuf_unref"); + gdk_drawable_unref = (Ptr_gdk_drawable_unref)libgtk.resolve("gdk_drawable_unref"); + gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)libgtk.resolve("gdk_drawable_get_depth"); + gdk_color_free = (Ptr_gdk_color_free)libgtk.resolve("gdk_color_free"); + gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)libgtk.resolve("gdk_x11_window_set_user_time"); + gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)libgtk.resolve("gdk_x11_drawable_get_xid"); + gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)libgtk.resolve("gdk_x11_drawable_get_xdisplay"); + + gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)libgtk.resolve("gtk_widget_set_default_direction"); + gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_fg"); + gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_bg"); + gtk_arrow_new = (Ptr_gtk_arrow_new)libgtk.resolve("gtk_arrow_new"); + gtk_menu_item_new = (Ptr_gtk_menu_item_new)libgtk.resolve("gtk_menu_item_new"); + gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)libgtk.resolve("gtk_check_menu_item_new"); + gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)libgtk.resolve("gtk_menu_bar_new"); + gtk_menu_new = (Ptr_gtk_menu_new)libgtk.resolve("gtk_menu_new"); + gtk_toolbar_new = (Ptr_gtk_toolbar_new)libgtk.resolve("gtk_toolbar_new"); + gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)libgtk.resolve("gtk_separator_tool_item_new"); + gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)libgtk.resolve("gtk_toolbar_insert"); + gtk_button_new = (Ptr_gtk_button_new)libgtk.resolve("gtk_button_new"); + gtk_tool_button_new = (Ptr_gtk_tool_button_new)libgtk.resolve("gtk_tool_button_new"); + gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)libgtk.resolve("gtk_hbutton_box_new"); + gtk_check_button_new = (Ptr_gtk_check_button_new)libgtk.resolve("gtk_check_button_new"); + gtk_radio_button_new = (Ptr_gtk_radio_button_new)libgtk.resolve("gtk_radio_button_new"); + gtk_notebook_new = (Ptr_gtk_notebook_new)libgtk.resolve("gtk_notebook_new"); + gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)libgtk.resolve("gtk_progress_bar_new"); + gtk_spin_button_new = (Ptr_gtk_spin_button_new)libgtk.resolve("gtk_spin_button_new"); + gtk_hscale_new = (Ptr_gtk_hscale_new)libgtk.resolve("gtk_hscale_new"); + gtk_vscale_new = (Ptr_gtk_vscale_new)libgtk.resolve("gtk_vscale_new"); + gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)libgtk.resolve("gtk_hscrollbar_new"); + gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)libgtk.resolve("gtk_vscrollbar_new"); + gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)libgtk.resolve("gtk_scrolled_window_new"); + gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)libgtk.resolve("gtk_menu_shell_append"); + gtk_entry_new = (Ptr_gtk_entry_new)libgtk.resolve("gtk_entry_new"); + gtk_tree_view_new = (Ptr_gtk_tree_view_new)libgtk.resolve("gtk_tree_view_new"); + gtk_combo_box_new = (Ptr_gtk_combo_box_new)libgtk.resolve("gtk_combo_box_new"); + gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)libgtk.resolve("gtk_progress_set_adjustment"); + gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)libgtk.resolve("gtk_range_set_adjustment"); + gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)libgtk.resolve("gtk_range_set_inverted"); + gtk_container_add = (Ptr_gtk_container_add)libgtk.resolve("gtk_container_add"); + gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)libgtk.resolve("gtk_icon_factory_lookup_default"); + gtk_icon_theme_get_default = (Ptr_gtk_icon_theme_get_default)libgtk.resolve("gtk_icon_theme_get_default"); + gtk_widget_style_get = (Ptr_gtk_widget_style_get)libgtk.resolve("gtk_widget_style_get"); + gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)libgtk.resolve("gtk_icon_set_render_icon"); + gtk_fixed_new = (Ptr_gtk_fixed_new)libgtk.resolve("gtk_fixed_new"); + gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)libgtk.resolve("gtk_tree_view_column_new"); + gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )libgtk.resolve("gtk_tree_view_append_column"); + gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )libgtk.resolve("gtk_tree_view_get_column"); + gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check"); + gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box"); + gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)libgtk.resolve("gtk_paint_flat_box"); + gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check"); + gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box"); + gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)libgtk.resolve("gtk_paint_resize_grip"); + gtk_paint_focus = (Ptr_gtk_paint_focus)libgtk.resolve("gtk_paint_focus"); + gtk_paint_shadow = (Ptr_gtk_paint_shadow)libgtk.resolve("gtk_paint_shadow"); + gtk_paint_slider = (Ptr_gtk_paint_slider)libgtk.resolve("gtk_paint_slider"); + gtk_paint_expander = (Ptr_gtk_paint_expander)libgtk.resolve("gtk_paint_expander"); + gtk_paint_handle = (Ptr_gtk_paint_handle)libgtk.resolve("gtk_paint_handle"); + gtk_paint_option = (Ptr_gtk_paint_option)libgtk.resolve("gtk_paint_option"); + gtk_paint_arrow = (Ptr_gtk_paint_arrow)libgtk.resolve("gtk_paint_arrow"); + gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)libgtk.resolve("gtk_paint_box_gap"); + gtk_paint_extension = (Ptr_gtk_paint_extension)libgtk.resolve("gtk_paint_extension"); + gtk_paint_hline = (Ptr_gtk_paint_hline)libgtk.resolve("gtk_paint_hline"); + gtk_paint_vline = (Ptr_gtk_paint_vline)libgtk.resolve("gtk_paint_vline"); + gtk_adjustment_new = (Ptr_gtk_adjustment_new)libgtk.resolve("gtk_adjustment_new"); + gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)libgtk.resolve("gtk_menu_item_set_submenu"); + gtk_settings_get_default = (Ptr_gtk_settings_get_default)libgtk.resolve("gtk_settings_get_default"); + gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)libgtk.resolve("gtk_separator_menu_item_new"); + gtk_frame_new = (Ptr_gtk_frame_new)libgtk.resolve("gtk_frame_new"); + gtk_expander_new = (Ptr_gtk_expander_new)libgtk.resolve("gtk_expander_new"); + gtk_statusbar_new = (Ptr_gtk_statusbar_new)libgtk.resolve("gtk_statusbar_new"); + gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)libgtk.resolve("gtk_combo_box_entry_new"); + gtk_container_forall = (Ptr_gtk_container_forall)libgtk.resolve("gtk_container_forall"); + gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)libgtk.resolve("gtk_widget_size_allocate"); + gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)libgtk.resolve("gtk_widget_set_direction"); + gtk_widget_path =(Ptr_gtk_widget_path)libgtk.resolve("gtk_widget_path"); + gtk_container_get_type =(Ptr_gtk_container_get_type)libgtk.resolve("gtk_container_get_type"); + gtk_window_get_type =(Ptr_gtk_window_get_type)libgtk.resolve("gtk_window_get_type"); + gtk_widget_get_type =(Ptr_gtk_widget_get_type)libgtk.resolve("gtk_widget_get_type"); + gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)libgtk.resolve("gtk_rc_get_style_by_paths"); + gtk_check_version =(Ptr_gtk_check_version)libgtk.resolve("gtk_check_version"); + pango_font_description_get_size = (Ptr_pango_font_description_get_size)libgtk.resolve("pango_font_description_get_size"); + pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)libgtk.resolve("pango_font_description_get_weight"); + pango_font_description_get_family = (Ptr_pango_font_description_get_family)libgtk.resolve("pango_font_description_get_family"); + pango_font_description_get_style = (Ptr_pango_font_description_get_style)libgtk.resolve("pango_font_description_get_style"); + + gnome_icon_lookup_sync = (Ptr_gnome_icon_lookup_sync)QLibrary::resolve(QLS("gnomeui-2"), 0, "gnome_icon_lookup_sync"); + gnome_vfs_init= (Ptr_gnome_vfs_init)QLibrary::resolve(QLS("gnomevfs-2"), 0, "gnome_vfs_init"); +} + +/* \internal + * Initializes a number of gtk menu widgets. + * The widgets are cached. + */ +void QGtkStylePrivate::initGtkMenu() +{ + // Create menubar + GtkWidget *gtkMenuBar = QGtkStylePrivate::gtk_menu_bar_new(); + setupGtkWidget(gtkMenuBar); + + GtkWidget *gtkMenuBarItem = QGtkStylePrivate::gtk_menu_item_new(); + gtk_menu_shell_append((GtkMenuShell*)(gtkMenuBar), gtkMenuBarItem); + gtk_widget_realize(gtkMenuBarItem); + + // Create menu + GtkWidget *gtkMenu = QGtkStylePrivate::gtk_menu_new(); + gtk_menu_item_set_submenu((GtkMenuItem*)(gtkMenuBarItem), gtkMenu); + gtk_widget_realize(gtkMenu); + + GtkWidget *gtkMenuItem = QGtkStylePrivate::gtk_menu_item_new(); + gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuItem); + gtk_widget_realize(gtkMenuItem); + + GtkWidget *gtkCheckMenuItem = QGtkStylePrivate::gtk_check_menu_item_new(); + gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkCheckMenuItem); + gtk_widget_realize(gtkCheckMenuItem); + + GtkWidget *gtkMenuSeparator = QGtkStylePrivate::gtk_separator_menu_item_new(); + gtk_menu_shell_append((GtkMenuShell*)gtkMenu, gtkMenuSeparator); + + addAllSubWidgets(gtkMenuBar); + addAllSubWidgets(gtkMenu); +} + + +void QGtkStylePrivate::initGtkTreeview() +{ + GtkWidget *gtkTreeView = gtk_tree_view_new(); + gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, gtk_tree_view_column_new()); + gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, gtk_tree_view_column_new()); + gtk_tree_view_append_column((GtkTreeView*)gtkTreeView, gtk_tree_view_column_new()); + addWidget(gtkTreeView); +} + + +/* \internal + * Initializes a number of gtk widgets that we can later on use to determine some of our styles. + * The widgets are cached. + */ +void QGtkStylePrivate::initGtkWidgets() +{ + // From gtkmain.c + uid_t ruid = getuid (); + uid_t rgid = getgid (); + uid_t euid = geteuid (); + uid_t egid = getegid (); + if (ruid != euid || rgid != egid) { + qWarning("\nThis process is currently running setuid or setgid.\nGTK+ does not allow this " + "therefore Qt cannot use the GTK+ integration.\nTry launching your app using \'gksudo\', " + "\'kdesudo\' or a similar tool.\n\n" + "See http://www.gtk.org/setuid.html for more information.\n"); + return; + } + + static QString themeName; + if (!gtkWidgetMap()->contains(QLS("GtkWindow")) && themeName.isEmpty()) { + themeName = getThemeName(); + + if (themeName.isEmpty()) { + qWarning("QGtkStyle was unable to detect the current GTK+ theme."); + return; + } else if (themeName == QLS("Qt") || themeName == QLS("Qt4")) { + // Due to namespace conflicts with Qt3 and obvious recursion with Qt4, + // we cannot support the GTK_Qt Gtk engine + qWarning("QGtkStyle cannot be used together with the GTK_Qt engine."); + return; + } + } + + if (QGtkStylePrivate::gtk_init) { + // Gtk will set the Qt error handler so we have to reset it afterwards + x11ErrorHandler qt_x_errhandler = XSetErrorHandler(0); + QGtkStylePrivate::gtk_init (NULL, NULL); + XSetErrorHandler(qt_x_errhandler); + + // make a window + GtkWidget* gtkWindow = QGtkStylePrivate::gtk_window_new(GTK_WINDOW_POPUP); + QGtkStylePrivate::gtk_widget_realize(gtkWindow); + if (displayDepth == -1) + displayDepth = QGtkStylePrivate::gdk_drawable_get_depth(gtkWindow->window); + gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow); + + + // Make all other widgets. respect the text direction + if (qApp->layoutDirection() == Qt::RightToLeft) + QGtkStylePrivate::gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL); + + if (!gtkWidgetMap()->contains(QLS("GtkButton"))) { + GtkWidget *gtkButton = QGtkStylePrivate::gtk_button_new(); + addWidget(gtkButton); + g_signal_connect(gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), this); + addWidget(QGtkStylePrivate::gtk_tool_button_new(NULL, NULL)); + addWidget(QGtkStylePrivate::gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE)); + addWidget(QGtkStylePrivate::gtk_hbutton_box_new()); + addWidget(QGtkStylePrivate::gtk_check_button_new()); + addWidget(QGtkStylePrivate::gtk_radio_button_new(NULL)); + addWidget(QGtkStylePrivate::gtk_combo_box_new()); + addWidget(QGtkStylePrivate::gtk_combo_box_entry_new()); + addWidget(QGtkStylePrivate::gtk_entry_new()); + addWidget(QGtkStylePrivate::gtk_frame_new(NULL)); + addWidget(QGtkStylePrivate::gtk_expander_new("")); + addWidget(QGtkStylePrivate::gtk_statusbar_new()); + addWidget(QGtkStylePrivate::gtk_hscale_new((GtkAdjustment*)(QGtkStylePrivate::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); + addWidget(QGtkStylePrivate::gtk_hscrollbar_new(NULL)); + addWidget(QGtkStylePrivate::gtk_scrolled_window_new(NULL, NULL)); + + initGtkMenu(); + addWidget(QGtkStylePrivate::gtk_notebook_new()); + addWidget(QGtkStylePrivate::gtk_progress_bar_new()); + addWidget(QGtkStylePrivate::gtk_spin_button_new((GtkAdjustment*) + (QGtkStylePrivate::gtk_adjustment_new(1, 0, 1, 0, 0, 0)), 0.1, 3)); + GtkWidget *toolbar = gtk_toolbar_new(); + g_signal_connect (toolbar, "notify::toolbar-style", G_CALLBACK (update_toolbar_style), toolbar); + gtk_toolbar_insert((GtkToolbar*)toolbar, gtk_separator_tool_item_new(), -1); + addWidget(toolbar); + initGtkTreeview(); + addWidget(gtk_vscale_new((GtkAdjustment*)(QGtkStylePrivate::gtk_adjustment_new(1, 0, 1, 0, 0, 0)))); + addWidget(gtk_vscrollbar_new(NULL)); + } + else // Rebuild map + { + // When styles change subwidgets can get rearranged + // as with the combo box. We need to update the widget map + // to reflect this; + QHash<QString, GtkWidget*> oldMap = *gtkWidgetMap(); + gtkWidgetMap()->clear(); + QHashIterator<QString, GtkWidget*> it(oldMap); + while (it.hasNext()) { + it.next(); + if (!it.key().contains(QLatin1Char('.'))) { + addAllSubWidgets(it.value()); + } + } + } + } else { + qWarning("QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries."); + } +} + +/*! \internal + * destroys all previously buffered widgets. + */ +void QGtkStylePrivate::cleanupGtkWidgets() +{ + if (gtkWidgetMap()->contains(QLS("GtkWindow"))) // Gtk will destroy all children + gtk_widget_destroy(gtkWidgetMap()->value(QLS("GtkWindow"))); +} + +static bool resolveGConf() +{ + if (!QGtkStylePrivate::gconf_client_get_default) { + QGtkStylePrivate::gconf_client_get_default = (Ptr_gconf_client_get_default)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_default"); + QGtkStylePrivate::gconf_client_get_string = (Ptr_gconf_client_get_string)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_string"); + QGtkStylePrivate::gconf_client_get_bool = (Ptr_gconf_client_get_bool)QLibrary::resolve(QLS("gconf-2"), 4, "gconf_client_get_bool"); + } + return (QGtkStylePrivate::gconf_client_get_default !=0); +} + +QString QGtkStylePrivate::getGConfString(const QString &value, const QString &fallback) +{ + QString retVal = fallback; + if (resolveGConf()) { + g_type_init(); + GConfClient* client = gconf_client_get_default(); + GError *err = 0; + char *str = gconf_client_get_string(client, qPrintable(value), &err); + if (!err) { + retVal = QString::fromUtf8(str); + g_free(str); + } + g_object_unref(client); + if (err) + g_error_free (err); + } + return retVal; +} + +bool QGtkStylePrivate::getGConfBool(const QString &key, bool fallback) +{ + bool retVal = fallback; + if (resolveGConf()) { + g_type_init(); + GConfClient* client = gconf_client_get_default(); + GError *err = 0; + bool result = gconf_client_get_bool(client, qPrintable(key), &err); + g_object_unref(client); + if (!err) + retVal = result; + else + g_error_free (err); + } + return retVal; +} + +QString QGtkStylePrivate::getThemeName() const +{ + QString themeName; + // We try to parse the gtkrc file first + // primarily to avoid resolving Gtk functions if + // the KDE 3 "Qt" style is currently in use + QString rcPaths = QString::fromLocal8Bit(qgetenv("GTK2_RC_FILES")); + if (!rcPaths.isEmpty()) { + QStringList paths = rcPaths.split(QLS(":")); + foreach (const QString &rcPath, paths) { + if (!rcPath.isEmpty()) { + QFile rcFile(rcPath); + if (rcFile.exists() && rcFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&rcFile); + while(!in.atEnd()) { + QString line = in.readLine(); + if (line.contains(QLS("gtk-theme-name"))) { + line = line.right(line.length() - line.indexOf(QLatin1Char('=')) - 1); + line.remove(QLatin1Char('\"')); + line = line.trimmed(); + themeName = line; + break; + } + } + } + } + if (!themeName.isEmpty()) + break; + } + } + + // Fall back to gconf + if (themeName.isEmpty() && resolveGConf()) + themeName = getGConfString(QLS("/desktop/gnome/interface/gtk_theme")); + + return themeName; +} + +// Get size of the arrow controls in a GtkSpinButton +int QGtkStylePrivate::getSpinboxArrowSize() const +{ + const int MIN_ARROW_WIDTH = 6; + GtkWidget *spinButton = gtkWidget(QLS("GtkSpinButton")); + GtkStyle *style = spinButton->style; + gint size = pango_font_description_get_size (style->font_desc); + gint arrow_size; + arrow_size = qMax(PANGO_PIXELS (size), MIN_ARROW_WIDTH) + style->xthickness; + arrow_size += arrow_size%2 + 1; + return arrow_size; +} + + +bool QGtkStylePrivate::isKDE4Session() +{ + static int version = -1; + if (version == -1) + version = qgetenv("KDE_SESSION_VERSION").toInt(); + return (version == 4); +} + +void QGtkStylePrivate::applyCustomPaletteHash() +{ + QPalette menuPal = gtkWidgetPalette(QLS("GtkMenu")); + GdkColor gdkBg = gtkWidget(QLS("GtkMenu"))->style->bg[GTK_STATE_NORMAL]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + menuPal.setBrush(QPalette::Base, bgColor); + menuPal.setBrush(QPalette::Window, bgColor); + qApp->setPalette(menuPal, "QMenu"); + + QPalette toolbarPal = gtkWidgetPalette(QLS("GtkToolbar")); + qApp->setPalette(toolbarPal, "QToolBar"); + + QPalette menuBarPal = gtkWidgetPalette(QLS("GtkMenuBar")); + qApp->setPalette(menuBarPal, "QMenuBar"); +} + +/*! \internal + * Returns the gtk Widget that should be used to determine text foreground and background colors. +*/ +GtkWidget* QGtkStylePrivate::getTextColorWidget() const +{ + return gtkWidget(QLS("GtkEntry")); +} + +void QGtkStylePrivate::setupGtkWidget(GtkWidget* widget) +{ + if (Q_GTK_IS_WIDGET(widget)) { + static GtkWidget* protoLayout = 0; + if (!protoLayout) { + protoLayout = QGtkStylePrivate::gtk_fixed_new(); + QGtkStylePrivate::gtk_container_add((GtkContainer*)(gtkWidgetMap()->value(QLS("GtkWindow"))), protoLayout); + } + Q_ASSERT(protoLayout); + + if (!widget->parent && !GTK_WIDGET_TOPLEVEL(widget)) + QGtkStylePrivate::gtk_container_add((GtkContainer*)(protoLayout), widget); + QGtkStylePrivate::gtk_widget_realize(widget); + } +} + +void QGtkStylePrivate::addWidgetToMap(GtkWidget *widget) +{ + if (Q_GTK_IS_WIDGET(widget)) { + gtk_widget_realize(widget); + gtkWidgetMap()->insert(classPath(widget), widget); + } + } + +void QGtkStylePrivate::addAllSubWidgets(GtkWidget *widget, gpointer v) +{ + Q_UNUSED(v); + addWidgetToMap(widget); + if (GTK_CHECK_TYPE ((widget), gtk_container_get_type())) + gtk_container_forall((GtkContainer*)widget, addAllSubWidgets, NULL); +} + +// Updates window/windowtext palette based on the indicated gtk widget +QPalette QGtkStylePrivate::gtkWidgetPalette(const QString >kWidgetName) +{ + GtkWidget *gtkWidget = QGtkStylePrivate::gtkWidget(gtkWidgetName); + Q_ASSERT(gtkWidget); + QPalette pal = QApplication::palette(); + GdkColor gdkBg = gtkWidget->style->bg[GTK_STATE_NORMAL]; + GdkColor gdkText = gtkWidget->style->fg[GTK_STATE_NORMAL]; + GdkColor gdkDisabledText = gtkWidget->style->fg[GTK_STATE_INSENSITIVE]; + QColor bgColor(gdkBg.red>>8, gdkBg.green>>8, gdkBg.blue>>8); + QColor textColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8); + QColor disabledTextColor(gdkDisabledText.red>>8, gdkDisabledText.green>>8, gdkDisabledText.blue>>8); + pal.setBrush(QPalette::Window, bgColor); + pal.setBrush(QPalette::Button, bgColor); + pal.setBrush(QPalette::All, QPalette::WindowText, textColor); + pal.setBrush(QPalette::Disabled, QPalette::WindowText, disabledTextColor); + pal.setBrush(QPalette::All, QPalette::ButtonText, textColor); + pal.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledTextColor); + return pal; +} + + +void QGtkStyleUpdateScheduler::updateTheme( QGtkStylePrivate* stylePrivate ) +{ + static QString oldTheme(QLS("qt_not_set")); + QPixmapCache::clear(); + + QFont font = QGtkStylePrivate::getThemeFont(); + if (QApplication::font() != font) + qApp->setFont(font); + + if (oldTheme != stylePrivate->getThemeName()) { + oldTheme = stylePrivate->getThemeName(); + QPalette newPalette = qApp->style()->standardPalette(); + QApplicationPrivate::setSystemPalette(newPalette); + QApplication::setPalette(newPalette); + stylePrivate->initGtkWidgets(); + stylePrivate->applyCustomPaletteHash(); + QList<QWidget*> widgets = QApplication::allWidgets(); + // Notify all widgets that size metrics might have changed + foreach (QWidget *widget, widgets) { + QEvent e(QEvent::StyleChange); + QApplication::sendEvent(widget, &e); + } + } + QIconLoader::instance()->updateSystemTheme(); +} + +void QGtkStylePrivate::addWidget(GtkWidget *widget) +{ + if (widget) { + setupGtkWidget(widget); + addAllSubWidgets(widget); + } +} + + +// Fetch the application font from the pango font description +// contained in the theme. +QFont QGtkStylePrivate::getThemeFont() +{ + QFont font; + GtkStyle *style = gtkStyle(); + if (style && qApp->desktopSettingsAware()) + { + PangoFontDescription *gtk_font = style->font_desc; + font.setPointSizeF((float)(pango_font_description_get_size(gtk_font))/PANGO_SCALE); + + QString family = QString::fromLatin1(pango_font_description_get_family(gtk_font)); + if (!family.isEmpty()) + font.setFamily(family); + + int weight = pango_font_description_get_weight(gtk_font); + if (weight >= PANGO_WEIGHT_HEAVY) + font.setWeight(QFont::Black); + else if (weight >= PANGO_WEIGHT_BOLD) + font.setWeight(QFont::Bold); + else if (weight >= PANGO_WEIGHT_SEMIBOLD) + font.setWeight(QFont::DemiBold); + else if (weight >= PANGO_WEIGHT_NORMAL) + font.setWeight(QFont::Normal); + else + font.setWeight(QFont::Light); + + PangoStyle fontstyle = pango_font_description_get_style(gtk_font); + if (fontstyle == PANGO_STYLE_ITALIC) + font.setStyle(QFont::StyleItalic); + else if (fontstyle == PANGO_STYLE_OBLIQUE) + font.setStyle(QFont::StyleOblique); + else + font.setStyle(QFont::StyleNormal); + } + return font; +} + + +// ----------- Native file dialogs ----------- + +// Extract filter list from expressions of type: foo (*.a *.b *.c)" +QStringList QGtkStylePrivate::extract_filter(const QString &rawFilter) +{ + QString result = rawFilter; + QRegExp r(QString::fromLatin1("^([^()]*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$")); + int index = r.indexIn(result); + if (index >= 0) + result = r.cap(2); + return result.split(QLatin1Char(' ')); +} + +extern QStringList qt_make_filter_list(const QString &filter); + +void QGtkStylePrivate::setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, + const QString &dir, const QString &filter, QString *selectedFilter, + QFileDialog::Options options, bool isSaveDialog, + QMap<GtkFileFilter *, QString> *filterMap) +{ + g_object_set(gtkFileChooser, "do-overwrite-confirmation", gboolean(!(options & QFileDialog::DontConfirmOverwrite)), NULL); + g_object_set(gtkFileChooser, "local_only", gboolean(true), NULL); + if (!filter.isEmpty()) { + QStringList filters = qt_make_filter_list(filter); + foreach (const QString &rawfilter, filters) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_filter_new (); + QString name = rawfilter.left(rawfilter.indexOf(QLatin1Char('('))); + QStringList extensions = extract_filter(rawfilter); + QGtkStylePrivate::gtk_file_filter_set_name(gtkFilter, qPrintable(name.isEmpty() ? extensions.join(QLS(", ")) : name)); + + foreach (const QString &fileExtension, extensions) { + // Note Gtk file dialogs are by default case sensitive + // and only supports basic glob syntax so we + // rewrite .xyz to .[xX][yY][zZ] + QString caseInsensitive; + for (int i = 0 ; i < fileExtension.length() ; ++i) { + QChar ch = fileExtension.at(i); + if (ch.isLetter()) { + caseInsensitive.append( + QLatin1Char('[') + + ch.toLower() + + ch.toUpper() + + QLatin1Char(']')); + } else { + caseInsensitive.append(ch); + } + } + QGtkStylePrivate::gtk_file_filter_add_pattern (gtkFilter, qPrintable(caseInsensitive)); + + } + if (filterMap) + filterMap->insert(gtkFilter, rawfilter); + QGtkStylePrivate::gtk_file_chooser_add_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); + if (selectedFilter && (rawfilter == *selectedFilter)) + QGtkStylePrivate::gtk_file_chooser_set_filter((GtkFileChooser*)gtkFileChooser, gtkFilter); + } + } + + // Using the currently active window is not entirely correct, however + // it gives more sensible behavior for applications that do not provide a + // parent + QWidget *modalFor = parent ? parent->window() : qApp->activeWindow(); + if (modalFor) { + QGtkStylePrivate::gtk_widget_realize(gtkFileChooser); // Creates X window + XSetTransientForHint(QGtkStylePrivate::gdk_x11_drawable_get_xdisplay(gtkFileChooser->window), + QGtkStylePrivate::gdk_x11_drawable_get_xid(gtkFileChooser->window), + modalFor->winId()); + QGtkStylePrivate::gdk_x11_window_set_user_time (gtkFileChooser->window, QX11Info::appUserTime()); + + } + + QFileInfo fileinfo(dir); + if (dir.isEmpty()) + fileinfo.setFile(QDir::currentPath()); + fileinfo.makeAbsolute(); + if (fileinfo.isDir()) { + QGtkStylePrivate::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); + } else if (isSaveDialog) { + QGtkStylePrivate::gtk_file_chooser_set_current_folder((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.absolutePath())); + QGtkStylePrivate::gtk_file_chooser_set_current_name((GtkFileChooser*)gtkFileChooser, qPrintable(fileinfo.fileName())); + } else { + QGtkStylePrivate::gtk_file_chooser_set_filename((GtkFileChooser*)gtkFileChooser, qPrintable(dir)); + } +} + +QString QGtkStylePrivate::openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + QMap<GtkFileFilter *, QString> filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); + filename = QString::fromUtf8(gtk_filename); + g_free (gtk_filename); + if (selectedFilter) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); + *selectedFilter = filterMap.value(gtkFilter); + } + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filename; +} + + +QString QGtkStylePrivate::openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) +{ + QMap<GtkFileFilter *, QString> filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + setupGtkFileChooser(gtkFileChooser, parent, dir, QString(), 0, options); + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); + filename = QString::fromUtf8(gtk_filename); + g_free (gtk_filename); + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filename; +} + +QStringList QGtkStylePrivate::openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + QStringList filenames; + QMap<GtkFileFilter *, QString> filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, false, &filterMap); + g_object_set(gtkFileChooser, "select-multiple", gboolean(true), NULL); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + if (gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + GSList *gtk_file_names = QGtkStylePrivate::gtk_file_chooser_get_filenames((GtkFileChooser*)gtkFileChooser); + for (GSList *iterator = gtk_file_names ; iterator; iterator = iterator->next) + filenames << QString::fromUtf8((const char*)iterator->data); + g_slist_free(gtk_file_names); + if (selectedFilter) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); + *selectedFilter = filterMap.value(gtkFilter); + } + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filenames; +} + +QString QGtkStylePrivate::saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) +{ + QMap<GtkFileFilter *, QString> filterMap; + GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + setupGtkFileChooser(gtkFileChooser, parent, dir, filter, selectedFilter, options, true, &filterMap); + + QWidget modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + QString filename; + if (QGtkStylePrivate::gtk_dialog_run ((GtkDialog*)gtkFileChooser) == GTK_RESPONSE_ACCEPT) { + char *gtk_filename = QGtkStylePrivate::gtk_file_chooser_get_filename ((GtkFileChooser*)gtkFileChooser); + filename = QString::fromUtf8(gtk_filename); + g_free (gtk_filename); + if (selectedFilter) { + GtkFileFilter *gtkFilter = QGtkStylePrivate::gtk_file_chooser_get_filter ((GtkFileChooser*)gtkFileChooser); + *selectedFilter = filterMap.value(gtkFilter); + } + } + + QApplicationPrivate::leaveModal(&modal_widget); + gtk_widget_destroy (gtkFileChooser); + return filename; +} + +QIcon QGtkStylePrivate::getFilesystemIcon(const QFileInfo &info) +{ + QIcon icon; + if (gnome_vfs_init && gnome_icon_lookup_sync) { + gnome_vfs_init(); + GtkIconTheme *theme = gtk_icon_theme_get_default(); + QByteArray fileurl = QUrl::fromLocalFile(info.absoluteFilePath()).toEncoded(); + char * icon_name = gnome_icon_lookup_sync(theme, + NULL, + fileurl.data(), + NULL, + GNOME_ICON_LOOKUP_FLAGS_NONE, + NULL); + QString iconName = QString::fromUtf8(icon_name); + g_free(icon_name); + if (iconName.startsWith(QLatin1Char('/'))) + return QIcon(iconName); + return QIcon::fromTheme(iconName); + } + return icon; +} + +QT_END_NAMESPACE + +#endif // !defined(QT_NO_STYLE_GTK) diff --git a/src/gui/styles/gtksymbols_p.h b/src/gui/styles/qgtkstyle_p.h index 313d948..fa16769 100644 --- a/src/gui/styles/gtksymbols_p.h +++ b/src/gui/styles/qgtkstyle_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef GTKSYMBOLS_H -#define GTKSYMBOLS_H +#ifndef QGTKSTYLE_P_H +#define QGTKSTYLE_P_H // // W A R N I N G @@ -56,19 +56,19 @@ #include <QtCore/qglobal.h> #if !defined(QT_NO_STYLE_GTK) +#include <QtGui/QFileDialog> + +#include <QtGui/QGtkStyle> +#include <private/qcleanlooksstyle_p.h> + #undef signals // Collides with GTK stymbols #include <gtk/gtk.h> -#include <QtCore/QLibrary> -#include <QtGui/QFont> -#include <QtGui/QFileDialog> + typedef unsigned long XID; #undef GTK_OBJECT_FLAGS #define GTK_OBJECT_FLAGS(obj)(((GtkObject*)(obj))->flags) -#define Q_GTK_TYPE_WIDGET QGtk::gtk_widget_get_type() -#define Q_GTK_IS_WIDGET(widget) widget && GTK_CHECK_TYPE ((widget), Q_GTK_TYPE_WIDGET) -#define Q_GTK_TYPE_WINDOW QGtk::gtk_window_get_type() -#define Q_GTK_TYPE_CONTAINER QGtk::gtk_container_get_type() +#define Q_GTK_IS_WIDGET(widget) widget && GTK_CHECK_TYPE ((widget), QGtkStylePrivate::gtk_widget_get_type()) #define QLS(x) QLatin1String(x) @@ -96,6 +96,7 @@ typedef GtkWidget* (*Ptr_gtk_combo_box_entry_new)(void); typedef GtkWidget* (*Ptr_gtk_toolbar_new)(void); typedef GtkWidget* (*Ptr_gtk_spin_button_new)(GtkAdjustment*, double, int); typedef GtkWidget* (*Ptr_gtk_button_new)(void); +typedef GtkWidget* (*Ptr_gtk_tool_button_new)(GtkWidget *, const gchar *); typedef GtkWidget* (*Ptr_gtk_hbutton_box_new)(void); typedef GtkWidget* (*Ptr_gtk_check_button_new)(void); typedef GtkWidget* (*Ptr_gtk_radio_button_new)(GSList *); @@ -197,6 +198,35 @@ typedef XID (*Ptr_gdk_x11_drawable_get_xid) (GdkDrawable *); typedef Display* (*Ptr_gdk_x11_drawable_get_xdisplay) ( GdkDrawable *); +QT_BEGIN_NAMESPACE + +typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, + const QString &filter, QString *selectedFilter, QFileDialog::Options options); +typedef QString (*_qt_filedialog_open_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, + const QString &filter, QString *selectedFilter, QFileDialog::Options options); +typedef QString (*_qt_filedialog_save_filename_hook) (QWidget * parent, const QString &caption, const QString &dir, + const QString &filter, QString *selectedFilter, QFileDialog::Options options); +typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, + QFileDialog::Options options); + +extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook; +extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook; +extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook; +extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook; + +class QGtkStylePrivate; + +class QGtkStyleFilter : public QObject +{ +public: + QGtkStyleFilter(QGtkStylePrivate* sp) + : stylePrivate(sp) + {} +private: + QGtkStylePrivate* stylePrivate; + bool eventFilter(QObject *obj, QEvent *e); +}; + typedef enum { GNOME_ICON_LOOKUP_FLAGS_NONE = 0, GNOME_ICON_LOOKUP_FLAGS_EMBEDDING_TEXT = 1<<0, @@ -219,21 +249,41 @@ typedef char* (*Ptr_gnome_icon_lookup_sync) ( GnomeIconLookupFlags flags, GnomeIconLookupResultFlags *result); -QT_BEGIN_NAMESPACE -class QGtk +class QGtkStylePrivate : public QCleanlooksStylePrivate { + Q_DECLARE_PUBLIC(QGtkStyle) public: + QGtkStylePrivate(); + + QGtkStyleFilter filter; + static GtkWidget* gtkWidget(const QString &path); static GtkStyle* gtkStyle(const QString &path = QLatin1String("GtkWindow")); - static void cleanup_gtk_widgets(); - static void initGtkWidgets(); + virtual void resolveGtk(); + virtual void initGtkMenu(); + virtual void initGtkTreeview(); + virtual void initGtkWidgets(); + + static void cleanupGtkWidgets(); + static bool isKDE4Session(); - static void applyCustomPaletteHash(); + void applyCustomPaletteHash(); static QFont getThemeFont(); static bool isThemeAvailable() { return gtkStyle() != 0; } + static bool getGConfBool(const QString &key, bool fallback = 0); + static QString getGConfString(const QString &key, const QString &fallback = QString()); + + virtual QString getThemeName() const; + virtual int getSpinboxArrowSize() const; + + static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, + const QString &dir, const QString &filter, QString *selectedFilter, + QFileDialog::Options options, bool isSaveDialog = false, + QMap<GtkFileFilter *, QString> *filterMap = 0); + static QString openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); static QString saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, @@ -241,8 +291,6 @@ public: static QString openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options); static QStringList openFilenames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); - static QString getGConfString(const QString &key, const QString &fallback = QString()); - static bool getGConfBool(const QString &key, bool fallback = 0); static QIcon getFilesystemIcon(const QFileInfo &); static Ptr_gtk_container_forall gtk_container_forall; @@ -261,6 +309,7 @@ public: static Ptr_gtk_menu_new gtk_menu_new; static Ptr_gtk_expander_new gtk_expander_new; static Ptr_gtk_button_new gtk_button_new; + static Ptr_gtk_tool_button_new gtk_tool_button_new; static Ptr_gtk_hbutton_box_new gtk_hbutton_box_new; static Ptr_gtk_check_button_new gtk_check_button_new; static Ptr_gtk_radio_button_new gtk_radio_button_new; @@ -362,6 +411,29 @@ public: static Ptr_gnome_icon_lookup_sync gnome_icon_lookup_sync; static Ptr_gnome_vfs_init gnome_vfs_init; + + virtual QPalette gtkWidgetPalette(const QString >kWidgetName); + +protected: + typedef QHash<QString, GtkWidget*> WidgetMap; + + static inline WidgetMap *gtkWidgetMap() + { + static WidgetMap *map = 0; + if (!map) + map = new WidgetMap(); + return map; + } + + static QStringList extract_filter(const QString &rawFilter); + + virtual GtkWidget* getTextColorWidget() const; + static void setupGtkWidget(GtkWidget* widget); + static void addWidgetToMap(GtkWidget* widget); + static void addAllSubWidgets(GtkWidget *widget, gpointer v = 0); + static void addWidget(GtkWidget *widget); + + virtual void init(); }; // Helper to ensure that we have polished all our gtk widgets @@ -370,10 +442,10 @@ class QGtkStyleUpdateScheduler : public QObject { Q_OBJECT public slots: - void updateTheme(); + void updateTheme( QGtkStylePrivate* stylePrivate ); }; QT_END_NAMESPACE #endif // !QT_NO_STYLE_GTK -#endif // GTKSYMBOLS_H +#endif // QGTKSTYLE_P_H diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 63ba641..38c3feb 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -342,12 +342,12 @@ void drawTabBase(QPainter *p, const QStyleOptionTabBarBaseV2 *tbb, const QWidget borderHighlightTop = QColor(207, 207, 207); } p->setPen(borderHighlightTop); - p->drawLine(0, 0, width, 0); + p->drawLine(tabRect.x(), 0, width, 0); p->setPen(borderTop); - p->drawLine(0, 1, width, 1); + p->drawLine(tabRect.x(), 1, width, 1); // center block - QRect centralRect(0, 2, width, height - 2); + QRect centralRect(tabRect.x(), 2, width, height - 2); if (active) { QColor mainColor = QColor(120, 120, 120); p->fillRect(centralRect, mainColor); @@ -370,9 +370,9 @@ void drawTabBase(QPainter *p, const QStyleOptionTabBarBaseV2 *tbb, const QWidget borderBottom = QColor(127, 127, 127); } p->setPen(borderHighlightBottom); - p->drawLine(0, height - 2, width, height - 2); + p->drawLine(tabRect.x(), height - 2, width, height - 2); p->setPen(borderBottom); - p->drawLine(0, height - 1, width, height - 1); + p->drawLine(tabRect.x(), height - 1, width, height - 1); } /* @@ -3637,17 +3637,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter break; } } + bool stretchTabs = (!verticalTabs && tabRect.height() > 22 || verticalTabs && tabRect.width() > 22); + switch (tp) { case QStyleOptionTab::Beginning: tdi.position = kHIThemeTabPositionFirst; - if (sp != QStyleOptionTab::NextIsSelected) + if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; break; case QStyleOptionTab::Middle: tdi.position = kHIThemeTabPositionMiddle; if (selected) tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; - if (sp != QStyleOptionTab::NextIsSelected) // Also when we're selected. + if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) // Also when we're selected. tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; break; case QStyleOptionTab::End: @@ -3659,9 +3661,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tdi.position = kHIThemeTabPositionOnly; break; } - // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves. - if ((!verticalTabs && tabRect.height() > 21 || verticalTabs && tabRect.width() > 21)) { + if (stretchTabs) { HIRect hirect = CGRectMake(0, 0, 23, 23); QPixmap pm(23, 23); pm.fill(Qt::transparent); diff --git a/src/gui/styles/qmotifstyle.cpp b/src/gui/styles/qmotifstyle.cpp index e6c60cf..b65d45c 100644 --- a/src/gui/styles/qmotifstyle.cpp +++ b/src/gui/styles/qmotifstyle.cpp @@ -1154,7 +1154,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q menuitem->palette, menuitem->state & State_Enabled, menuitem->text, QPalette::Text); textWidth = menuitem->fontMetrics.width(menuitem->text) + 10; - y += menuitem->fontMetrics.lineSpacing() / 2; + y += menuitem->fontMetrics.height() / 2; p->setFont(oldFont); } p->setPen(opt->palette.dark().color()); @@ -2056,7 +2056,7 @@ QMotifStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, if (mi->menuItemType == QStyleOptionMenuItem::Separator) { w = 10; - h = (mi->text.isEmpty()) ? motifSepHeight : mi->fontMetrics.lineSpacing(); + h = (mi->text.isEmpty()) ? motifSepHeight : mi->fontMetrics.height(); } // a little bit of border can never harm diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index ce2109a..f880351 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -5027,7 +5027,7 @@ QSize QPlastiqueStyle::sizeFromContents(ContentsType type, const QStyleOption *o case CT_MenuItem: if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) - newSize.setHeight(menuItem->text.isEmpty() ? 2 : menuItem->fontMetrics.lineSpacing()); + newSize.setHeight(menuItem->text.isEmpty() ? 2 : menuItem->fontMetrics.height()); } break; case CT_MenuBarItem: @@ -5514,9 +5514,6 @@ int QPlastiqueStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, case PM_MenuHMargin: ret = 0; break; - case PM_ToolBarIconSize: - ret = 24; - break; case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: ret = 1; @@ -5607,11 +5604,11 @@ int QPlastiqueStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, #ifdef QT3_SUPPORT if (widget && widget->inherits("Q3DockWindowTitleBar")) { // Q3DockWindow has smaller title bars than QDockWidget - ret = qMax(widget->fontMetrics().lineSpacing(), 20); + ret = qMax(widget->fontMetrics().height(), 20); } else #endif - ret = qMax(widget ? widget->fontMetrics().lineSpacing() : - (option ? option->fontMetrics.lineSpacing() : 0), 30); + ret = qMax(widget ? widget->fontMetrics().height() : + (option ? option->fontMetrics.height() : 0), 30); break; case PM_MaximumDragDistance: return -1; diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 4c6bc46..b87f3a8 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -66,7 +66,6 @@ #include "qtextedit.h" #include "qtoolbar.h" #include "qtoolbutton.h" -#include "qtreeview.h" #include "qfocusframe.h" #include "private/qtoolbarextension_p.h" @@ -91,14 +90,14 @@ static const qreal goldenRatio = 1.618; const layoutHeader QS60StylePrivate::m_layoutHeaders[] = { // *** generated layout data *** -{240,320,1,14,true,"QVGA Landscape Mirrored"}, -{240,320,1,14,false,"QVGA Landscape"}, -{320,240,1,14,true,"QVGA Portrait Mirrored"}, -{320,240,1,14,false,"QVGA Portrait"}, -{360,640,1,14,true,"NHD Landscape Mirrored"}, -{360,640,1,14,false,"NHD Landscape"}, -{640,360,1,14,true,"NHD Portrait Mirrored"}, -{640,360,1,14,false,"NHD Portrait"}, +{240,320,1,15,true,"QVGA Landscape Mirrored"}, +{240,320,1,15,false,"QVGA Landscape"}, +{320,240,1,15,true,"QVGA Portrait Mirrored"}, +{320,240,1,15,false,"QVGA Portrait"}, +{360,640,1,15,true,"NHD Landscape Mirrored"}, +{360,640,1,15,false,"NHD Landscape"}, +{640,360,1,15,true,"NHD Portrait Mirrored"}, +{640,360,1,15,false,"NHD Portrait"}, {352,800,1,12,true,"E90 Landscape Mirrored"}, {352,800,1,12,false,"E90 Landscape"} // *** End of generated data *** @@ -108,16 +107,16 @@ const int QS60StylePrivate::m_numberOfLayouts = const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = { // *** generated pixel metrics *** -{5,0,-909,0,0,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,51,27,51,4,4,5,10,15,-909,5,58,12,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, -{5,0,-909,0,0,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,51,27,51,4,4,5,10,15,-909,5,58,12,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, -{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, -{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1}, -{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, -{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, -{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,98,35,98,5,5,6,8,19,-909,7,74,22,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, -{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,98,35,98,5,5,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1}, -{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,5,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,8,6,5,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1}, -{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1} +{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,-909,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,3,3,4,9,13,-909,5,51,11,5,0,6,3,3,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1}, +{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,-909,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,3,3,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1}, +{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,7,4,4,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1}, +{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1}, +{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,8,5,5,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,5,5,6,8,19,-909,7,74,22,7,0,8,5,5,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,5,5,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1}, +{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,5,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,8,6,5,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1}, +{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1} // *** End of generated data *** }; @@ -526,7 +525,8 @@ void QS60StylePrivate::drawPart(QS60StyleEnums::SkinParts skinPart, #else true; #endif - const QPixmap skinPartPixMap((doCache ? cachedPart : part)(skinPart, rect.size(), flags)); + + const QPixmap skinPartPixMap((doCache ? cachedPart : part)(skinPart, rect.size(), painter, flags)); if (!skinPartPixMap.isNull()) painter->drawPixmap(rect.topLeft(), skinPartPixMap); } @@ -593,14 +593,14 @@ void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start, } QPixmap QS60StylePrivate::cachedPart(QS60StyleEnums::SkinParts part, - const QSize &size, SkinElementFlags flags) + const QSize &size, QPainter *painter, SkinElementFlags flags) { QPixmap result; const QString cacheKey = QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinPartFlags=%4") .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags); if (!QPixmapCache::find(cacheKey, result)) { - result = QS60StylePrivate::part(part, size, flags); + result = QS60StylePrivate::part(part, size, painter, flags); QPixmapCache::insert(cacheKey, result); } return result; @@ -1315,13 +1315,13 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, painter->setClipRect(voptAdj.rect); const bool isSelected = (vopt->state & QStyle::State_Selected); - bool isVisible = false; + bool isScrollBarVisible = false; int scrollBarWidth = 0; QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget); for (int i = 0; i < scrollBars.size(); ++i) { QScrollBar *scrollBar = scrollBars.at(i); if (scrollBar && scrollBar->orientation() == Qt::Vertical) { - isVisible = scrollBar->isVisible(); + isScrollBarVisible = scrollBar->isVisible(); scrollBarWidth = scrollBar->size().width(); break; } @@ -1329,7 +1329,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, int rightValue = widget ? widget->contentsRect().right() : 0; - if (isVisible) + if (isScrollBarVisible) rightValue -= scrollBarWidth; if (voptAdj.rect.right() > rightValue) @@ -1337,49 +1337,51 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, const QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &voptAdj, widget); QRect textRect = subElementRect(SE_ItemViewItemText, &voptAdj, widget); + const QAbstractItemView *itemView = qobject_cast<const QAbstractItemView *>(widget); // draw themed background for table unless background brush has been defined. if (vopt->backgroundBrush == Qt::NoBrush) { - const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option); - const QTableView *table = qobject_cast<const QTableView *>(widget); - if (table && tableOption) { - const QModelIndex index = tableOption->index; + if (itemView) { + const QModelIndex index = vopt->index; //todo: Draw cell background only once - for the first cell. QStyleOptionViewItemV4 voptAdj2 = voptAdj; - const QModelIndex indexFirst = table->model()->index(0,0); - const QModelIndex indexLast = table->model()->index( - table->model()->rowCount()-1,table->model()->columnCount()-1); - if (table->viewport()) - voptAdj2.rect = QRect( table->visualRect(indexFirst).topLeft(), - table->visualRect(indexLast).bottomRight()).intersect(table->viewport()->rect()); - drawPrimitive(PE_PanelItemViewItem, &voptAdj2, painter, widget); + const QModelIndex indexFirst = itemView->model()->index(0,0); + const QModelIndex indexLast = itemView->model()->index( + itemView->model()->rowCount()-1,itemView->model()->columnCount()-1); + if (itemView->viewport()) + voptAdj2.rect = QRect( itemView->visualRect(indexFirst).topLeft(), + itemView->visualRect(indexLast).bottomRight()).intersect(itemView->viewport()->rect()); + drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget); } - } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);} + } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, &voptAdj, painter, widget);} // draw the focus rect if (isSelected) { QRect highlightRect = option->rect.adjusted(1,1,-1,-1); - const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); - if (view && view->selectionBehavior() != QAbstractItemView::SelectItems) { + QAbstractItemView::SelectionBehavior selectionBehavior = + itemView ? itemView->selectionBehavior() : QAbstractItemView::SelectItems; + if (selectionBehavior != QAbstractItemView::SelectItems) { // set highlight rect so that it is continuous from cell to cell, yet sligthly // smaller than cell rect int xBeginning = 0, yBeginning = 0, xEnd = 0, yEnd = 0; - if (view->selectionBehavior() == QAbstractItemView::SelectRows) { + if (selectionBehavior == QAbstractItemView::SelectRows) { yBeginning = 1; yEnd = -1; if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) xBeginning = 1; else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) xEnd = -1; - } else if (view->selectionBehavior() == QAbstractItemView::SelectColumns) { + } else if (selectionBehavior == QAbstractItemView::SelectColumns) { xBeginning = 1; xEnd = -1; if (vopt->viewItemPosition == QStyleOptionViewItemV4::Beginning) yBeginning = 1; else if (vopt->viewItemPosition == QStyleOptionViewItemV4::End) yEnd = -1; } - highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, xBeginning); + highlightRect = option->rect.adjusted(xBeginning, yBeginning, xEnd, yEnd); } - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags); + if (vopt->showDecorationSelected && + (vopt->palette.highlight().color() == d->themePalette()->highlight().color())) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags); } // draw the icon @@ -1388,48 +1390,44 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state); // Draw selection check mark. Show check mark only in multi selection modes. - if (const QListView *listView = (qobject_cast<const QListView *>(widget))) { + if (itemView) { const bool singleSelection = - listView && - (listView->selectionMode() == QAbstractItemView::SingleSelection || - listView->selectionMode() == QAbstractItemView::NoSelection); + (itemView->selectionMode() == QAbstractItemView::SingleSelection || + itemView->selectionMode() == QAbstractItemView::NoSelection); const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget); + + QStyleOptionViewItemV4 checkMarkOption(voptAdj); + // Draw selection mark. if (voptAdj.state & QStyle::State_Selected && !singleSelection) { - QStyleOptionViewItemV4 option(voptAdj); - option.rect = selectionRect; - // Draw selection mark. - drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget); + checkMarkOption.rect = selectionRect; + drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); if ( textRect.right() > selectionRect.left() ) textRect.setRight(selectionRect.left()); } else if (singleSelection && - voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) { - // draw the check mark - if (selectionRect.isValid()) { - QStyleOptionViewItemV4 option(*vopt); - option.rect = selectionRect; - option.state = option.state & ~QStyle::State_HasFocus; - - switch (vopt->checkState) { - case Qt::Unchecked: - option.state |= QStyle::State_Off; - break; - case Qt::PartiallyChecked: - option.state |= QStyle::State_NoChange; - break; - case Qt::Checked: - option.state |= QStyle::State_On; - break; - } - drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget); + voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator && + selectionRect.isValid()) { + checkMarkOption.rect = selectionRect; + checkMarkOption.state = checkMarkOption.state & ~QStyle::State_HasFocus; + + switch (vopt->checkState) { + case Qt::Unchecked: + checkMarkOption.state |= QStyle::State_Off; + break; + case Qt::PartiallyChecked: + checkMarkOption.state |= QStyle::State_NoChange; + break; + case Qt::Checked: + checkMarkOption.state |= QStyle::State_On; + break; } + drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &checkMarkOption, painter, widget); } } // draw the text if (!voptAdj.text.isEmpty()) { - const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option); if (isSelected) { - if (qobject_cast<const QTableView *>(widget) && tableOption) + if (qobject_cast<const QTableView *>(widget)) voptAdj.palette.setColor( QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0)); else @@ -1722,8 +1720,11 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, // direction is set to north (and south when in RightToLeft) const QS60StylePrivate::SkinElementFlag arrowDirection = (arrowOptions.direction == Qt::LeftToRight) ? QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointSouth; + painter->save(); + painter->setPen(option->palette.windowText().color()); QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubMenu, painter, arrowOptions.rect, (flags | QS60StylePrivate::SF_ColorSkinned | arrowDirection)); + painter->restore(); } //draw text @@ -1830,8 +1831,12 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, break; #endif //QT_NO_TOOLBAR case CE_ShapedFrame: - if (qobject_cast<const QTextEdit *>(widget)) { - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_Editor, painter, option->rect, flags); + if (const QTextEdit *textEdit = qobject_cast<const QTextEdit *>(widget)) { + const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option); + if (frame->palette.base().color()==Qt::transparent) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_Editor, painter, option->rect, flags); + else + QCommonStyle::drawControl(element, option, painter, widget); } else if (qobject_cast<const QTableView *>(widget)) { QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableItem, painter, option->rect, flags); } else if (const QHeaderView *header = qobject_cast<const QHeaderView *>(widget)) { @@ -1889,6 +1894,17 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, painter->restore(); } break; + case CE_Splitter: + if (option->state & State_Sunken && option->state & State_Enabled) { + painter->save(); + painter->setOpacity(0.5); + painter->setBrush(d->themePalette()->light()); + painter->setRenderHint(QPainter::Antialiasing); + const qreal roundRectRadius = 4 * goldenRatio; + painter->drawRoundedRect(option->rect, roundRectRadius, roundRectRadius); + painter->restore(); + } + break; default: QCommonStyle::drawControl(element, option, painter, widget); } @@ -1899,6 +1915,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, */ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { + Q_D(const QS60Style); const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled; switch (element) { #ifndef QT_NO_LINEEDIT @@ -1908,19 +1925,27 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti if (widget && qobject_cast<const QComboBox *>(widget->parentWidget())) break; #endif - QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_FrameLineEdit, - painter, option->rect, flags); + QBrush editBrush = option->palette.brush(QPalette::Base); + if (editBrush.color() == Qt::transparent) + QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_FrameLineEdit, + painter, option->rect, flags); + else + QCommonStyle::drawPrimitive(element, option, painter, widget); } break; #endif // QT_NO_LINEEDIT case PE_IndicatorCheckBox: { - const QRect indicatorRect = option->rect; // Draw checkbox indicator as color skinned graphics. const QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ? QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff; - QS60StylePrivate::drawSkinPart(skinPart, painter, indicatorRect, - (flags | QS60StylePrivate::SF_ColorSkinned)); + painter->save(); + QColor themeColor = d->s60Color(QS60StyleEnums::CL_QsnIconColors, 13, option); + QColor buttonTextColor = option->palette.buttonText().color(); + if (themeColor != buttonTextColor) + painter->setPen(buttonTextColor); + QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags | QS60StylePrivate::SF_ColorSkinned ); + painter->restore(); } break; case PE_IndicatorViewItemCheck: @@ -1960,21 +1985,33 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti const int newY = (buttonRect.bottomRight().y() - option->rect.bottomRight().y()) >> 1 ; buttonRect.adjust(0,-newY,0,-newY); + painter->save(); + QColor themeColor = d->s60Color(QS60StyleEnums::CL_QsnIconColors, 13, option); + QColor buttonTextColor = option->palette.buttonText().color(); + if (themeColor != buttonTextColor) + painter->setPen(buttonTextColor); + // Draw radiobutton indicator as color skinned graphics. QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ? QS60StyleEnums::SP_QgnIndiRadiobuttOn : QS60StyleEnums::SP_QgnIndiRadiobuttOff; QS60StylePrivate::drawSkinPart(skinPart, painter, buttonRect, (flags | QS60StylePrivate::SF_ColorSkinned)); + painter->restore(); } break; case PE_PanelButtonCommand: case PE_PanelButtonTool: case PE_PanelButtonBevel: case PE_FrameButtonBevel: { - const bool isPressed = option->state & QStyle::State_Sunken; - const QS60StylePrivate::SkinElements skinElement = - isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; - QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + QBrush editBrush = option->palette.brush(QPalette::Base); + if (editBrush.color() == Qt::transparent) { + const bool isPressed = option->state & QStyle::State_Sunken; + const QS60StylePrivate::SkinElements skinElement = + isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal; + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } else { + QCommonStyle::drawPrimitive(element, option, painter, widget); + } } break; #ifndef QT_NO_TOOLBUTTON @@ -2001,21 +2038,29 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti case PE_IndicatorSpinUp: if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { QStyleOptionSpinBox optionSpinBox = *spinBox; - const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ? - QS60StyleEnums::SP_QgnGrafScrollArrowUp : - QS60StyleEnums::SP_QgnGrafScrollArrowDown; - const int adjustment = qMin(optionSpinBox.rect.width(), optionSpinBox.rect.height())/6; - optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment ); - QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect,flags); + if (optionSpinBox.palette.base().color()==Qt::transparent) { + const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ? + QS60StyleEnums::SP_QgnGrafScrollArrowUp : + QS60StyleEnums::SP_QgnGrafScrollArrowDown; + const int adjustment = qMin(optionSpinBox.rect.width(), optionSpinBox.rect.height())/6; + optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment ); + QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect,flags); + } else { + QCommonStyle::drawPrimitive(element, &optionSpinBox, painter, widget); + } } #ifndef QT_NO_COMBOBOX else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) { - // We want to draw down arrow here for comboboxes as well. - const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown; - QStyleOptionFrame comboBox = *cmb; - const int adjustment = qMin(comboBox.rect.width(), comboBox.rect.height())/6; - comboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment ); - QS60StylePrivate::drawSkinPart(part, painter, comboBox.rect,flags); + if (cmb->palette.base().color()==Qt::transparent) { + // We want to draw down arrow here for comboboxes as well. + const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown; + QStyleOptionFrame comboBox = *cmb; + const int adjustment = qMin(comboBox.rect.width(), comboBox.rect.height())/6; + comboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment ); + QS60StylePrivate::drawSkinPart(part, painter, comboBox.rect,flags); + } else { + QCommonStyle::drawPrimitive(element, cmb, painter, widget); + } } #endif //QT_NO_COMBOBOX break; @@ -2045,8 +2090,12 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti || qobject_cast<const QMenu *> (widget) #endif //QT_NO_MENU ) { - QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_OptionsMenu; - QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + if (option->palette.base().color()==Qt::transparent) { + QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_OptionsMenu; + QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags); + } else { + QCommonStyle::drawPrimitive(element, option, painter, widget); + } } break; case PE_FrameWindow: @@ -2133,7 +2182,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti drawSkinPart = true; } - if ( drawSkinPart ) + if (drawSkinPart) QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags); if (option->state & State_Children) { @@ -2190,7 +2239,7 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const if (metricValue == KNotFound) metricValue = QCommonStyle::pixelMetric(metric, option, widget); - if (metric == PM_SubMenuOverlap && widget){ + if (metric == PM_SubMenuOverlap && widget) { const QMenu *menu = qobject_cast<const QMenu *>(widget); if (menu && menu->activeAction() && menu->activeAction()->menu()) { const int menuWidth = menu->activeAction()->menu()->sizeHint().width(); @@ -2878,7 +2927,7 @@ QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon, return QCommonStyle::standardIconImplementation(standardIcon, option, widget); } const QS60StylePrivate::SkinElementFlags flags = adjustedFlags; - const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), flags)); + const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), 0, flags)); return cachedPixMap.isNull() ? QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap); } diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h index 8e53eee..54af757 100644 --- a/src/gui/styles/qs60style_p.h +++ b/src/gui/styles/qs60style_p.h @@ -372,7 +372,7 @@ public: SF_StateEnabled = 0x0010, // Enabled = the default SF_StateDisabled = 0x0020, - SF_ColorSkinned = 0x0040, + SF_ColorSkinned = 0x0040, // pixmap is colored with foreground pen color }; enum CacheClearReason { @@ -472,7 +472,7 @@ private: const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags); static QPixmap cachedPart(QS60StyleEnums::SkinParts part, const QSize &size, - SkinElementFlags flags = KDefaultSkinElementFlags); + QPainter *painter, SkinElementFlags flags = KDefaultSkinElementFlags); static QPixmap cachedFrame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags = KDefaultSkinElementFlags); @@ -489,7 +489,7 @@ private: static QSize partSize(QS60StyleEnums::SkinParts part, SkinElementFlags flags = KDefaultSkinElementFlags); static QPixmap part(QS60StyleEnums::SkinParts part, const QSize &size, - SkinElementFlags flags = KDefaultSkinElementFlags); + QPainter *painter, SkinElementFlags flags = KDefaultSkinElementFlags); static QFont s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize); diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 9765066..678844c 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -99,7 +99,7 @@ public: const QSize &size, QS60StylePrivate::SkinElementFlags flags); static QPixmap skinnedGraphics(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags); static QPixmap colorSkinnedGraphics(const QS60StyleEnums::SkinParts &stylepart, - const QSize &size, QS60StylePrivate::SkinElementFlags flags); + const QSize &size, QPainter *painter, QS60StylePrivate::SkinElementFlags flags); static QColor colorValue(const TAknsItemID &colorGroup, int colorIndex); static QPixmap fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, QImage::Format format); static bool disabledPartGraphic(QS60StyleEnums::SkinParts &part); @@ -112,14 +112,12 @@ private: const QSize &size, QS60StylePrivate::SkinElementFlags flags); static QPixmap createSkinnedGraphicsLX(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags); static QPixmap colorSkinnedGraphicsLX(const QS60StyleEnums::SkinParts &stylepart, - const QSize &size, QS60StylePrivate::SkinElementFlags flags); + const QSize &size, QPainter *painter, QS60StylePrivate::SkinElementFlags flags); static void frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID ¢erId); static TRect innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect); static void checkAndUnCompressBitmapL(CFbsBitmap*& aOriginalBitmap); static void checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap); static void unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap); - static void colorGroupAndIndex(QS60StyleEnums::SkinParts skinID, - TAknsItemID &colorGroup, int &colorIndex); static void fallbackInfo(const QS60StyleEnums::SkinParts &stylepart, TDes& fallbackFileName, TInt& fallbackIndex); static bool checkSupport(const int supportedRelease); static TAknsItemID checkAndUpdateReleaseSpecificGraphics(int part); @@ -361,11 +359,11 @@ QPixmap QS60StyleModeSpecifics::skinnedGraphics( } QPixmap QS60StyleModeSpecifics::colorSkinnedGraphics( - const QS60StyleEnums::SkinParts &stylepart, - const QSize &size, QS60StylePrivate::SkinElementFlags flags) + const QS60StyleEnums::SkinParts &stylepart, const QSize &size, QPainter *painter, + QS60StylePrivate::SkinElementFlags flags) { QPixmap colorGraphics; - TRAPD(error, QT_TRYCATCH_LEAVING(colorGraphics = colorSkinnedGraphicsLX(stylepart, size, flags))); + TRAPD(error, QT_TRYCATCH_LEAVING(colorGraphics = colorSkinnedGraphicsLX(stylepart, size, painter, flags))); return error ? QPixmap() : colorGraphics; } @@ -525,7 +523,7 @@ void QS60StyleModeSpecifics::fallbackInfo(const QS60StyleEnums::SkinParts &style QPixmap QS60StyleModeSpecifics::colorSkinnedGraphicsLX( const QS60StyleEnums::SkinParts &stylepart, - const QSize &size, QS60StylePrivate::SkinElementFlags flags) + const QSize &size, QPainter *painter, QS60StylePrivate::SkinElementFlags flags) { // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts. const int stylepartIndex = (int)stylepart; @@ -537,8 +535,13 @@ QPixmap QS60StyleModeSpecifics::colorSkinnedGraphicsLX( fallbackInfo(stylepart, fileNamePtr, fallbackGraphicID); TAknsItemID colorGroup = KAknsIIDQsnIconColors; - int colorIndex = 0; - colorGroupAndIndex(stylepart, colorGroup, colorIndex); + TRgb defaultColor = KRgbBlack; + int colorIndex = -1; //set a bogus value to color index to ensure that painter color is used + //to color the icon + if (painter) { + QRgb widgetColor = painter->pen().color().rgb(); + defaultColor = TRgb(qRed(widgetColor), qGreen(widgetColor), qBlue(widgetColor)); + } const bool rotatedBy90or270 = (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest)); @@ -550,7 +553,7 @@ QPixmap QS60StyleModeSpecifics::colorSkinnedGraphicsLX( fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); AknsUtils::CreateColorIconLC( - skinInstance, skinId, colorGroup, colorIndex, icon, iconMask, fileNamePtr, fallbackGraphicID , fallbackGraphicsMaskID, KRgbBlack); + skinInstance, skinId, colorGroup, colorIndex, icon, iconMask, fileNamePtr, fallbackGraphicID , fallbackGraphicsMaskID, defaultColor); User::LeaveIfError(AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved)); User::LeaveIfError(AknIconUtils::SetSize(iconMask, targetSize, EAspectRatioNotPreserved)); QPixmap result = fromFbsBitmap(icon, iconMask, flags, qt_TDisplayMode2Format(icon->DisplayMode())); @@ -652,8 +655,8 @@ QPoint qt_s60_fill_background_offset(const QWidget *targetWidget) } QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( - QS60StyleEnums::SkinParts part, - const QSize &size, QS60StylePrivate::SkinElementFlags flags) + QS60StyleEnums::SkinParts part, const QSize &size, + QS60StylePrivate::SkinElementFlags flags) { // this function can throw both exceptions and leaves. There are no cleanup dependencies between Qt and Symbian parts. if (!size.isValid()) @@ -700,13 +703,13 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( CleanupStack::PushL(background); User::LeaveIfError(background->Create(targetSize, EColor16MA)); - CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(background); + CFbsBitmapDevice *dev = CFbsBitmapDevice::NewL(background); CleanupStack::PushL(dev); - CFbsBitGc* gc = NULL; + CFbsBitGc *gc = NULL; User::LeaveIfError(dev->CreateContext(gc)); CleanupStack::PushL(gc); - CAknsBasicBackgroundControlContext* bgContext = CAknsBasicBackgroundControlContext::NewL( + CAknsBasicBackgroundControlContext *bgContext = CAknsBasicBackgroundControlContext::NewL( skinId, targetSize, EFalse); @@ -1145,12 +1148,12 @@ QPixmap QS60StyleModeSpecifics::generateMissingThemeGraphic(QS60StyleEnums::Skin } QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, - const QSize &size, SkinElementFlags flags) + const QSize &size, QPainter *painter, SkinElementFlags flags) { QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); QPixmap result = (flags & SF_ColorSkinned)? - QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, flags) + QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, painter, flags) : QS60StyleModeSpecifics::skinnedGraphics(part, size, flags); lock.relock(); @@ -1189,7 +1192,7 @@ QPixmap QS60StylePrivate::backgroundTexture() { if (!m_background) { QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, - QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), SkinElementFlags()); + QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), 0, SkinElementFlags()); m_background = new QPixmap(background); } return *m_background; @@ -1343,26 +1346,6 @@ QSize QS60StylePrivate::screenSize() return QSize(screenSize.iWidth, screenSize.iHeight); } -void QS60StyleModeSpecifics::colorGroupAndIndex( - QS60StyleEnums::SkinParts skinID, TAknsItemID &colorGroup, int &colorIndex) -{ - switch(skinID) { - case QS60StyleEnums::SP_QgnIndiSubMenu: - colorGroup = KAknsIIDQsnIconColors; - colorIndex = EAknsCIQsnIconColorsCG1; - break; - case QS60StyleEnums::SP_QgnIndiRadiobuttOff: - case QS60StyleEnums::SP_QgnIndiRadiobuttOn: - case QS60StyleEnums::SP_QgnIndiCheckboxOff: - case QS60StyleEnums::SP_QgnIndiCheckboxOn: - colorGroup = KAknsIIDQsnIconColors; - colorIndex = EAknsCIQsnIconColorsCG14; - break; - default: - break; - } -} - QS60Style::QS60Style() : QCommonStyle(*new QS60StylePrivate) { diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp index 8a2616d..14f0424 100644 --- a/src/gui/styles/qs60style_simulated.cpp +++ b/src/gui/styles/qs60style_simulated.cpp @@ -189,8 +189,10 @@ QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list, } QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, const QSize &size, - QS60StylePrivate::SkinElementFlags flags) + QPainter *painter, QS60StylePrivate::SkinElementFlags flags) { + Q_UNUSED(painter); + const QString partKey = QS60Style::partKeys().at(part); const QPicture partPicture = QS60StyleModeSpecifics::m_partPictures.value(partKey); QSize partSize(partPicture.boundingRect().size()); diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp index eef1573..ec238a9 100644 --- a/src/gui/styles/qstyle.cpp +++ b/src/gui/styles/qstyle.cpp @@ -2417,13 +2417,13 @@ int QStyle::layoutSpacingImplementation(QSizePolicy::ControlType /* control1 */, return -1; } -#if !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_STREAM) QT_BEGIN_INCLUDE_NAMESPACE #include <QDebug> QT_END_INCLUDE_NAMESPACE QDebug operator<<(QDebug debug, QStyle::State state) { +#if !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_STREAM) debug << "QStyle::State("; QStringList states; @@ -2455,9 +2455,9 @@ QDebug operator<<(QDebug debug, QStyle::State state) qSort(states); debug << states.join(QLatin1String(" | ")); debug << ')'; +#endif return debug; } -#endif /*! \since 4.6 diff --git a/src/gui/styles/qstyle.h b/src/gui/styles/qstyle.h index 1f8d5c8..0014954 100644 --- a/src/gui/styles/qstyle.h +++ b/src/gui/styles/qstyle.h @@ -878,9 +878,7 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::State) Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::SubControls) -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DEBUG) Q_GUI_EXPORT QDebug operator<<(QDebug debug, QStyle::State state); -#endif QT_END_NAMESPACE diff --git a/src/gui/styles/qstyleoption.cpp b/src/gui/styles/qstyleoption.cpp index 10a6b5b..f5a2b94 100644 --- a/src/gui/styles/qstyleoption.cpp +++ b/src/gui/styles/qstyleoption.cpp @@ -45,9 +45,7 @@ # include "private/qt_mac_p.h" # include "qmacstyle_mac.h" #endif -#ifndef QT_NO_DEBUG #include <qdebug.h> -#endif #include <QtCore/qmath.h> QT_BEGIN_NAMESPACE @@ -1254,7 +1252,7 @@ QStyleOptionViewItemV4::QStyleOptionViewItemV4(int version) \brief the features of the group box frame The frame is flat by default. - + \sa QStyleOptionFrameV2::FrameFeature */ @@ -4656,6 +4654,119 @@ QStyleOptionTabWidgetFrame::QStyleOptionTabWidgetFrame(int version) The default value is QSize(-1, -1), i.e. an invalid size. */ + + +/*! + + \class QStyleOptionTabWidgetFrameV2 + \brief The QStyleOptionTabWidgetFrameV2 class is used to describe the + parameters for drawing the frame around a tab widget. + + QStyleOptionTabWidgetFrameV2 contains all the information that + QStyle functions need to draw the frame around QTabWidget. + + For performance reasons, the access to the member variables is + direct (i.e., using the \c . or \c -> operator). This low-level feel + makes the structures straightforward to use and emphasizes that + these are simply parameters used by the style functions. + + For an example demonstrating how style options can be used, see + the \l {widgets/styles}{Styles} example. + + \sa QStyleOption, QTabWidget +*/ + + +/*! + \variable QStyleOptionTabWidgetFrameV2::tabBarRect + \brief the rectangle containing all the tabs + + The default value is a null rectangle, i.e. a rectangle with both + the width and the height set to 0. +*/ + +/*! + \variable QStyleOptionTabWidgetFrameV2::selectedTabRect + \brief the rectangle containing the selected tab + + This rectangle is contained within the tabBarRect. The default + value is a null rectangle, i.e. a rectangle with both the width + and the height set to 0. +*/ + + +/*! + Constructs a QStyleOptionTabWidgetFrameV2, initializing the members + variables to their default values. +*/ + +QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2() + : QStyleOptionTabWidgetFrame(Version) +{ +} + + +/*! \internal */ +QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2(int version) + : QStyleOptionTabWidgetFrame(version) +{ +} + + +/*! + Constructs a QStyleOptionTabWidgetFrameV2 copy of the \a other style option + which can be either of the QStyleOptionTabWidgetFrameV2 or + QStyleOptionTabWidgetFrame types. + + If the \a other style option's version is 1, the new style option's \l + selectedTabRect and tabBarRect will contain null rects + + \sa version +*/ +QStyleOptionTabWidgetFrameV2::QStyleOptionTabWidgetFrameV2(const QStyleOptionTabWidgetFrame &other) +{ + QStyleOptionTabWidgetFrameV2::operator=(other); + +} + + +/*! + Assigns the \a other style option to this style option. The \a + other style option can be either of the QStyleOptionFrameV2 or + QStyleOptionFrame types. + + If the \a{other} style option's version is 1, this style option's + \l FrameFeature value is set to \l QStyleOptionFrameV2::None. If + its version is 2, its \l FrameFeature value is simply copied to + this style option. +*/ +QStyleOptionTabWidgetFrameV2 &QStyleOptionTabWidgetFrameV2::operator=(const QStyleOptionTabWidgetFrame &other) +{ + QStyleOptionTabWidgetFrame::operator=(other); + if (const QStyleOptionTabWidgetFrameV2 *f2 = qstyleoption_cast<const QStyleOptionTabWidgetFrameV2 *>(&other)) { + selectedTabRect = f2->selectedTabRect; + tabBarRect = f2->tabBarRect; + } + return *this; +} + + +/*! + \enum QStyleOptionTabWidgetFrameV2::StyleOptionVersion + + This enum is used to hold information about the version of the style option, and + is defined for each QStyleOption subclass. + + \value Version 2 + + The version is used by QStyleOption subclasses to implement + extensions without breaking compatibility. If you use + qstyleoption_cast(), you normally do not need to check it. + + \sa StyleOptionType +*/ + + #endif // QT_NO_TABWIDGET #ifndef QT_NO_TABBAR @@ -5298,9 +5409,9 @@ QStyleHintReturnVariant::QStyleHintReturnVariant() : QStyleHintReturn(Version, T Returns a T or 0 depending on the type of \a hint. */ -#if !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_STREAM) QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType) { +#if !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_STREAM) switch (optionType) { case QStyleOption::SO_Default: debug << "SO_Default"; break; @@ -5361,19 +5472,21 @@ QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType) case QStyleOption::SO_GraphicsItem: debug << "SO_GraphicsItem"; break; } +#endif return debug; } QDebug operator<<(QDebug debug, const QStyleOption &option) { +#if !defined(QT_NO_DEBUG) && !defined(QT_NO_DEBUG_STREAM) debug << "QStyleOption("; debug << QStyleOption::OptionType(option.type); debug << ',' << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight"); debug << ',' << option.state; debug << ',' << option.rect; debug << ')'; +#endif return debug; } -#endif QT_END_NAMESPACE diff --git a/src/gui/styles/qstyleoption.h b/src/gui/styles/qstyleoption.h index 2860664..abd52bf 100644 --- a/src/gui/styles/qstyleoption.h +++ b/src/gui/styles/qstyleoption.h @@ -192,8 +192,28 @@ public: protected: QStyleOptionTabWidgetFrame(int version); }; + +class Q_GUI_EXPORT QStyleOptionTabWidgetFrameV2 : public QStyleOptionTabWidgetFrame +{ +public: + enum StyleOptionVersion { Version = 2 }; + + QRect tabBarRect; + QRect selectedTabRect; + + QStyleOptionTabWidgetFrameV2(); + QStyleOptionTabWidgetFrameV2(const QStyleOptionTabWidgetFrameV2 &other) : + QStyleOptionTabWidgetFrame(Version) { *this = other; } + QStyleOptionTabWidgetFrameV2(const QStyleOptionTabWidgetFrame &other); + QStyleOptionTabWidgetFrameV2 &operator=(const QStyleOptionTabWidgetFrame &other); + +protected: + QStyleOptionTabWidgetFrameV2(int version); +}; + #endif + #ifndef QT_NO_TABBAR class Q_GUI_EXPORT QStyleOptionTabBarBase : public QStyleOption { @@ -938,10 +958,8 @@ T qstyleoption_cast(QStyleHintReturn *hint) return 0; } -#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DEBUG) Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QStyleOption::OptionType &optionType); Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QStyleOption &option); -#endif QT_END_NAMESPACE diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 707b05e..ae1d33a 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -4325,7 +4325,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op QRenderRule subRule = renderRule(w, opt, PseudoElement_TabWidgetPane); if (subRule.hasNativeBorder()) { subRule.drawBackground(p, opt->rect); - QStyleOptionTabWidgetFrame frmCopy(*frm); + QStyleOptionTabWidgetFrameV2 frmCopy(*frm); subRule.configurePalette(&frmCopy.palette, QPalette::WindowText, QPalette::Window); baseStyle()->drawPrimitive(pe, &frmCopy, p, w); } else { @@ -4722,7 +4722,7 @@ int QStyleSheetStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const return subRule.size().height(); else if (subRule.hasBox() || subRule.hasBorder()) { QFontMetrics fm = opt ? opt->fontMetrics : w->fontMetrics(); - return subRule.size(QSize(0, fm.lineSpacing())).height(); + return subRule.size(QSize(0, fm.height())).height(); } break; } diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp index 5fa6251..7ed187f 100644 --- a/src/gui/styles/qwindowsmobilestyle.cpp +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -5347,10 +5347,8 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp painter->drawLines(a); break; } case PE_Frame: - if (d->doubleControls) - qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),2,&option->palette.light()); - else - qDrawPlainRect(painter, option->rect, option->palette.shadow().color(),1,&option->palette.light()); + qDrawPlainRect(painter, option->rect, option->palette.shadow().color(), + d->doubleControls ? 2 : 1, &option->palette.background()); break; case PE_FrameLineEdit: case PE_FrameMenu: @@ -6840,34 +6838,11 @@ void QWindowsMobileStyle::polish(QWidget *widget) { else #endif //QT_NO_TOOLBAR -#ifndef QT_NO_PROPERTIES - if (QAbstractButton *pushButton = qobject_cast<QAbstractButton*>(widget)) { - QVariant oldFont = widget->property("_q_styleWindowsMobileFont"); - if (!oldFont.isValid()) { - QFont f = pushButton->font(); - widget->setProperty("_q_styleWindowsMobileFont", f); - f.setBold(true); - int p = f.pointSize(); - if (p > 2) - f.setPointSize(p-1); - pushButton->setFont(f); - } - } -#endif - QWindowsStyle::polish(widget); + QWindowsStyle::polish(widget); } void QWindowsMobileStyle::unpolish(QWidget *widget) { -#ifndef QT_NO_PROPERTIES - if (QAbstractButton *pushButton = qobject_cast<QAbstractButton*>(widget)) { - QVariant oldFont = widget->property("_q_styleWindowsMobileFont"); - if (oldFont.isValid()) { - widget->setFont(qVariantValue<QFont>(oldFont)); - widget->setProperty("_q_styleWindowsMobileFont", QVariant()); - } - } -#endif QWindowsStyle::unpolish(widget); } diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 0f72440..5cf738e 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -454,9 +454,6 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); break; - case PM_ToolBarIconSize: - ret = int(QStyleHelper::dpiScaled(24.)); - break; case PM_DockWidgetTitleMargin: ret = int(QStyleHelper::dpiScaled(2.)); break; diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 6cb8b40..9f5440c 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -159,7 +159,7 @@ QWindowsVistaStyle::QWindowsVistaStyle() } //convert Qt state flags to uxtheme button states -int buttonStateId(int flags, int partId) +static int buttonStateId(int flags, int partId) { int stateId = 0; if (partId == BP_RADIOBUTTON || partId == BP_CHECKBOX) { @@ -190,7 +190,7 @@ int buttonStateId(int flags, int partId) return stateId; } -void Animation::paint(QPainter *painter, const QStyleOption *option) +void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option) { Q_UNUSED(option); Q_UNUSED(painter); @@ -205,7 +205,7 @@ void Animation::paint(QPainter *painter, const QStyleOption *option) + ((1-alpha)*_secondaryImage) */ -void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) { +void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) { if (_secondaryImage.isNull() || _primaryImage.isNull()) return; @@ -251,7 +251,7 @@ void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) { initial and final state of the transition, depending on the time difference between _startTime and current time. */ -void Transition::paint(QPainter *painter, const QStyleOption *option) +void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option) { float alpha = 1.0; if (_duration > 0) { @@ -278,7 +278,7 @@ void Transition::paint(QPainter *painter, const QStyleOption *option) secondary pulse images depending on the time difference between _startTime and current time. */ -void Pulse::paint(QPainter *painter, const QStyleOption *option) +void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option) { float alpha = 1.0; if (_duration > 0) { @@ -393,8 +393,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt startImage.fill(0); QPainter startPainter(&startImage); - Animation *anim = d->widgetAnimation(widget); - Transition *t = new Transition; + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + QWindowsVistaTransition *t = new QWindowsVistaTransition; t->setWidget(w); // If we have a running animation on the widget already, we will use that to paint the initial @@ -531,7 +531,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt case PE_IndicatorCheckBox: case PE_IndicatorRadioButton: { - if (Animation *a = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { a->paint(painter, option); } else { QWindowsXPStyle::drawPrimitive(element, option, painter, widget); @@ -644,7 +644,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt break; case PE_FrameLineEdit: - if (Animation *anim = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { anim->paint(painter, option); } else { QPainter *p = painter; @@ -929,13 +929,13 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (doTransition) { QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - Animation *anim = d->widgetAnimation(widget); + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); QStyleOptionButton opt = *button; opt.state = (QStyle::State)oldState; startImage.fill(0); - Transition *t = new Transition; + QWindowsVistaTransition *t = new QWindowsVistaTransition; t->setWidget(w); QPainter startPainter(&startImage); @@ -972,7 +972,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { - if (Animation *anim = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { anim->paint(painter, option); } else { name = QLatin1String("BUTTON"); @@ -999,14 +999,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption !(state & (State_Sunken | State_On)) && !(state & State_MouseOver) && (state & State_Enabled) && (state & State_Active)) { - Animation *anim = d->widgetAnimation(widget); + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); if (!anim && widget) { QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); startImage.fill(0); QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); alternateImage.fill(0); - Pulse *pulse = new Pulse; + QWindowsVistaPulse *pulse = new QWindowsVistaPulse; pulse->setWidget(const_cast<QWidget*>(widget)); QPainter startPainter(&startImage); @@ -1079,7 +1079,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) { if (((progressbar->value() > 0 && d->transitionsEnabled()) || isIndeterminate)) { if (!d->widgetAnimation(progressbar) && progressbar->value() < progressbar->maximum()) { - Animation *a = new Animation; + QWindowsVistaAnimation *a = new QWindowsVistaAnimation; a->setWidget(const_cast<QWidget*>(widget)); a->setStartTime(QTime::currentTime()); d->startAnimation(a); @@ -1095,7 +1095,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QTime current = QTime::currentTime(); if (isIndeterminate) { - if (Animation *a = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { int glowSize = 120; int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animOffset = a->startTime().msecsTo(current) / 4; @@ -1165,7 +1165,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } d->drawBackground(theme); - if (Animation *a = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) { int glowSize = 140; int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width()); int animOffset = a->startTime().msecsTo(current) / 4; @@ -1603,8 +1603,8 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle if (doTransition) { QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied); - Animation *anim = d->widgetAnimation(widget); - Transition *t = new Transition; + QWindowsVistaAnimation *anim = d->widgetAnimation(widget); + QWindowsVistaTransition *t = new QWindowsVistaTransition; t->setWidget(w); if (!anim) { if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) { @@ -1651,7 +1651,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle t->setDuration(500); } - if (Animation *anim = d->widgetAnimation(widget)) { + if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) { anim->paint(painter, option); return; } @@ -2217,14 +2217,15 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt int xpos = x; int margin = cb->frame ? 3 : 0; int bmarg = cb->frame ? 2 : 0; - xpos += wi - bmarg - 16; + int arrowButtonWidth = bmarg + 16; + xpos += wi - arrowButtonWidth; switch (subControl) { case SC_ComboBoxFrame: rect = cb->rect; break; case SC_ComboBoxArrow: - rect.setRect(xpos, y , wi - xpos, he); + rect.setRect(xpos, y , arrowButtonWidth, he); break; case SC_ComboBoxEditField: rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin); @@ -2533,7 +2534,7 @@ void QWindowsVistaStylePrivate::timerEvent() !animations[i]->running() || !QWindowsVistaStylePrivate::useVista()) { - Animation *a = animations.takeAt(i); + QWindowsVistaAnimation *a = animations.takeAt(i); delete a; } } @@ -2546,14 +2547,14 @@ void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w) { for (int i = animations.size() - 1 ; i >= 0 ; --i) { if (animations[i]->widget() == w) { - Animation *a = animations.takeAt(i); + QWindowsVistaAnimation *a = animations.takeAt(i); delete a; break; } } } -void QWindowsVistaStylePrivate::startAnimation(Animation *t) +void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t) { Q_Q(QWindowsVistaStyle); stopAnimation(t->widget()); @@ -2575,11 +2576,11 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const } -Animation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const +QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const { if (!widget) return 0; - foreach (Animation *a, animations) { + foreach (QWindowsVistaAnimation *a, animations) { if (a->widget() == widget) return a; } diff --git a/src/gui/styles/qwindowsvistastyle_p.h b/src/gui/styles/qwindowsvistastyle_p.h index e9bbb77..04823c1 100644 --- a/src/gui/styles/qwindowsvistastyle_p.h +++ b/src/gui/styles/qwindowsvistastyle_p.h @@ -136,11 +136,11 @@ QT_BEGIN_NAMESPACE #define TDLG_SECONDARYPANEL 8 #endif -class Animation +class QWindowsVistaAnimation { public : - Animation() : _running(true) { } - virtual ~Animation() { } + QWindowsVistaAnimation() : _running(true) { } + virtual ~QWindowsVistaAnimation() { } QWidget * widget() const { return _widget; } bool running() const { return _running; } const QTime &startTime() const { return _startTime; } @@ -161,11 +161,11 @@ protected: // Handles state transition animations -class Transition : public Animation +class QWindowsVistaTransition : public QWindowsVistaAnimation { public : - Transition() : Animation() {} - virtual ~Transition() { } + QWindowsVistaTransition() : QWindowsVistaAnimation() {} + virtual ~QWindowsVistaTransition() { } void setDuration(int duration) { _duration = duration; } void setStartImage(const QImage &image) { _primaryImage = image; } void setEndImage(const QImage &image) { _secondaryImage = image; } @@ -176,11 +176,11 @@ public : // Handles pulse animations (default buttons) -class Pulse: public Animation +class QWindowsVistaPulse: public QWindowsVistaAnimation { public : - Pulse() : Animation() {} - virtual ~Pulse() { } + QWindowsVistaPulse() : QWindowsVistaAnimation() {} + virtual ~QWindowsVistaPulse() { } void setDuration(int duration) { _duration = duration; } void setPrimaryImage(const QImage &image) { _primaryImage = image; } void setAlternateImage(const QImage &image) { _secondaryImage = image; } @@ -199,15 +199,15 @@ public: ~QWindowsVistaStylePrivate(); static bool resolveSymbols(); static inline bool useVista(); - void startAnimation(Animation *); + void startAnimation(QWindowsVistaAnimation *); void stopAnimation(const QWidget *); - Animation* widgetAnimation(const QWidget *) const; + QWindowsVistaAnimation* widgetAnimation(const QWidget *) const; void timerEvent(); bool transitionsEnabled() const; QWidget *treeViewHelper(); private: - QList <Animation*> animations; + QList <QWindowsVistaAnimation*> animations; QBasicTimer animationTimer; QWidget *m_treeViewHelper; }; diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 9ef30e5..fe7f5d7 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -47,6 +47,7 @@ #include <private/qpaintengine_raster_p.h> #include <private/qapplication_p.h> #include <private/qstylehelper_p.h> +#include <private/qwidget_p.h> #include <qlibrary.h> #include <qpainter.h> #include <qpaintengine.h> @@ -299,7 +300,11 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) if (!limboWidget) { limboWidget = new QWidget(0); + limboWidget->createWinId(); limboWidget->setObjectName(QLatin1String("xp_limbo_widget")); + // We dont need this internal widget to appear in QApplication::topLevelWidgets() + if (QWidgetPrivate::allWidgets) + QWidgetPrivate::allWidgets->remove(limboWidget); } return limboWidget->winId(); @@ -1577,7 +1582,7 @@ case PE_Frame: // This should work, but currently there's an error in the ::drawBackgroundDirectly() // code, when using the HDC directly.. if (useGradient) { - QStyleOptionTabWidgetFrame frameOpt = *tab; + QStyleOptionTabWidgetFrameV2 frameOpt = *tab; frameOpt.rect = widget->rect(); QRect contentsRect = subElementRect(SE_TabWidgetTabContents, &frameOpt, widget); QRegion reg = option->rect; @@ -2836,8 +2841,8 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo State bflags = toolbutton->state & ~State_Sunken; State mflags = bflags; - - if (bflags & State_AutoRaise) { + bool autoRaise = flags & State_AutoRaise; + if (autoRaise) { if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { bflags &= ~State_Raised; } @@ -2856,8 +2861,8 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo QStyleOption tool(0); tool.palette = toolbutton->palette; if (toolbutton->subControls & SC_ToolButton) { - if (flags & (State_Sunken | State_On | State_Raised) || !(flags & State_AutoRaise)) { - if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) { + if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) { + if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) { XPThemeData theme(widget, p, QLatin1String("TOOLBAR")); theme.partId = TP_SPLITBUTTON; theme.rect = button; @@ -2876,13 +2881,12 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo theme.stateId = stateId; d->drawBackground(theme); } else { - tool.rect = button; + tool.rect = option->rect; tool.state = bflags; - if (widget && !qobject_cast<QToolBar*>(widget->parentWidget()) - && !(bflags & State_AutoRaise)) - proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, widget); - else + if (autoRaise) // for tool bars proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); + else + proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, widget); } } } @@ -2899,13 +2903,40 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo QStyleOptionToolButton label = *toolbutton; label.state = bflags; int fw = 2; + if (!autoRaise) + label.state &= ~State_Sunken; label.rect = button.adjusted(fw, fw, -fw, -fw); proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); if (toolbutton->subControls & SC_ToolButtonMenu) { tool.rect = menuarea; tool.state = mflags; - proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + if (autoRaise) { + proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); + } else { + tool.state = mflags; + menuarea.adjust(-2, 0, 0, 0); + // Draw menu button + if ((bflags & State_Sunken) != (mflags & State_Sunken)){ + p->save(); + p->setClipRect(menuarea); + tool.rect = option->rect; + proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, 0); + p->restore(); + } + // Draw arrow + p->save(); + p->setPen(option->palette.dark().color()); + p->drawLine(menuarea.left(), menuarea.top() + 3, + menuarea.left(), menuarea.bottom() - 3); + p->setPen(option->palette.light().color()); + p->drawLine(menuarea.left() - 1, menuarea.top() + 3, + menuarea.left() - 1, menuarea.bottom() - 3); + + tool.rect = menuarea.adjusted(2, 3, -2, -1); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); + p->restore(); + } } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); QRect ir = toolbutton->rect; diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri index 767ade0..88a2cce 100644 --- a/src/gui/styles/styles.pri +++ b/src/gui/styles/styles.pri @@ -109,10 +109,10 @@ contains( styles, plastique ) { contains( styles, gtk ) { HEADERS += styles/qgtkstyle.h HEADERS += styles/qgtkpainter_p.h - HEADERS += styles/gtksymbols_p.h + HEADERS += styles/qgtkstyle_p.h SOURCES += styles/qgtkstyle.cpp SOURCES += styles/qgtkpainter.cpp - SOURCES += styles/gtksymbols.cpp + SOURCES += styles/qgtkstyle_p.cpp !contains( styles, cleanlooks ) { styles += cleanlooks DEFINES+= QT_STYLE_CLEANLOOKS diff --git a/src/gui/symbian/qsymbianevent.cpp b/src/gui/symbian/qsymbianevent.cpp index af2c861..2799e6f 100644 --- a/src/gui/symbian/qsymbianevent.cpp +++ b/src/gui/symbian/qsymbianevent.cpp @@ -66,13 +66,13 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QSymbianEvent::type() + \fn QSymbianEvent::type() const Returns the event type contained in the QSymbianEvent instance. */ /*! - \fn QSymbianEvent::isValid() + \fn QSymbianEvent::isValid() const Returns whether this QSymbianEvent instance contains a valid event. */ diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 1285935..447087c 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2324,22 +2324,22 @@ QDataStream &operator>>(QDataStream &s, QFont &font) */ QFontInfo::QFontInfo(const QFont &font) : d(font.d.data()) -{ d->ref.ref(); } +{ +} /*! Constructs a copy of \a fi. */ QFontInfo::QFontInfo(const QFontInfo &fi) - : d(fi.d) -{ d->ref.ref(); } + : d(fi.d.data()) +{ +} /*! Destroys the font info object. */ QFontInfo::~QFontInfo() { - if (!d->ref.deref()) - delete d; } /*! @@ -2347,7 +2347,7 @@ QFontInfo::~QFontInfo() */ QFontInfo &QFontInfo::operator=(const QFontInfo &fi) { - qAtomicAssign(d, fi.d); + d = fi.d.data(); return *this; } @@ -2632,7 +2632,7 @@ QFontCache::~QFontCache() while (it != end) { if (--it.value().data->cache_count == 0) { if (it.value().data->ref == 0) { - FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %g %d %d %d %d)", + FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %g %g %d %d %d)", it.value().data, it.key().script, it.key().def.pointSize, it.key().def.pixelSize, it.key().def.weight, it.key().def.style, it.key().def.fixedPitch); diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index d74f0b4..144a82d 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -86,7 +86,7 @@ struct QFontDef #endif // Q_WS_X11 qreal pointSize; - int pixelSize; + qreal pixelSize; uint styleStrategy : 16; uint styleHint : 8; diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 738e36a..fb8444e 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -1331,7 +1331,7 @@ static void match(int script, const QFontDef &request, " family: %s [%s], script: %d\n" " weight: %d, style: %d\n" " stretch: %d\n" - " pixelSize: %d\n" + " pixelSize: %g\n" " pitch: %c", family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(), foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(), diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp index ae26dab..6cde9ed 100644 --- a/src/gui/text/qfontdatabase_win.cpp +++ b/src/gui/text/qfontdatabase_win.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qt_windows.h" +#include <qmath.h> #include <private/qapplication_p.h> #include "qfont_p.h" #include "qfontengine_p.h" @@ -670,7 +671,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ break; } - lf.lfHeight = -request.pixelSize; + lf.lfHeight = -qRound(request.pixelSize); lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; @@ -899,7 +900,6 @@ static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &r return fe; } - void QFontDatabase::load(const QFontPrivate *d, int script) { // sanity checks @@ -910,8 +910,9 @@ void QFontDatabase::load(const QFontPrivate *d, int script) // normalize the request to get better caching QFontDef req = d->request; if (req.pixelSize <= 0) - req.pixelSize = qMax(1, qRound(req.pointSize * d->dpi / 72.)); - req.pointSize = 0; + req.pixelSize = qreal((req.pointSize * d->dpi) / 72.); + if (req.pixelSize < 1) + req.pixelSize = 1; if (req.weight == 0) req.weight = QFont::Normal; if (req.stretch == 0) @@ -928,7 +929,8 @@ void QFontDatabase::load(const QFontPrivate *d, int script) QFontEngine *fe = QFontCache::instance()->findEngine(key); // set it to the actual pointsize, so QFontInfo will do the right thing - req.pointSize = req.pixelSize*72./d->dpi; + if (req.pointSize < 0) + req.pointSize = req.pixelSize*72./d->dpi; if (!fe) { if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp index 382c4fe..f184811 100644 --- a/src/gui/text/qfontdatabase_x11.cpp +++ b/src/gui/text/qfontdatabase_x11.cpp @@ -51,6 +51,7 @@ #include <qfile.h> #include <qtemporaryfile.h> #include <qabstractfileengine.h> +#include <qmath.h> #include <ctype.h> #include <stdlib.h> @@ -752,12 +753,12 @@ QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request) if (X11->display) dpi = QX11Info::appDpiY(); else - dpi = 96; // #### + dpi = qt_defaultDpiY(); } double size; if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch) - fontDef.pixelSize = qRound(size); + fontDef.pixelSize = size; else fontDef.pixelSize = 12; @@ -1455,7 +1456,7 @@ void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontD slant_value = FC_SLANT_OBLIQUE; FcPatternAddInteger(pattern, FC_SLANT, slant_value); - double size_value = qMax(1, request.pixelSize); + double size_value = qMax(qreal(1.), request.pixelSize); FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value); int stretch = request.stretch; @@ -1893,8 +1894,9 @@ void QFontDatabase::load(const QFontPrivate *d, int script) // normalize the request to get better caching QFontDef req = d->request; if (req.pixelSize <= 0) - req.pixelSize = qRound(qt_pixelSize(req.pointSize, d->dpi)); - req.pointSize = 0; + req.pixelSize = floor(qt_pixelSize(req.pointSize, d->dpi) * 100 + 0.5) / 100; + if (req.pixelSize < 1) + req.pixelSize = 1; if (req.weight == 0) req.weight = QFont::Normal; if (req.stretch == 0) @@ -1909,7 +1911,9 @@ void QFontDatabase::load(const QFontPrivate *d, int script) return; // set it to the actual pointsize, so QFontInfo will do the right thing - req.pointSize = qt_pointSize(req.pixelSize, d->dpi); + if (req.pointSize < 0) + req.pointSize = qt_pointSize(req.pixelSize, d->dpi); + QFontEngine *fe = QFontCache::instance()->findEngine(key); diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 3da1593..4041717 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -327,7 +327,7 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id) void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing) { - *ysize = fontDef.pixelSize << 6; + *ysize = qRound(fontDef.pixelSize * 64); *xsize = *ysize * fontDef.stretch / 100; *outline_drawing = false; @@ -387,7 +387,9 @@ QFontEngine::Properties QFreetypeFace::properties() const p.descent = QFixed::fromFixed(-face->size->metrics.descender); p.leading = QFixed::fromFixed(face->size->metrics.height - face->size->metrics.ascender + face->size->metrics.descender); p.emSquare = face->size->metrics.y_ppem; - p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.); +// p.boundingBox = QRectF(-p.ascent.toReal(), 0, (p.ascent + p.descent).toReal(), face->size->metrics.max_advance/64.); + p.boundingBox = QRectF(0, -p.ascent.toReal(), + face->size->metrics.max_advance/64, (p.ascent + p.descent).toReal() ); } p.italicAngle = 0; p.capHeight = p.ascent; @@ -709,6 +711,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) hbFace = freetype->hbFace; metrics = face->size->metrics; + #if defined(Q_WS_QWS) /* TrueType fonts with embedded bitmaps may have a bitmap font specific @@ -1219,7 +1222,8 @@ QFixed QFontEngineFT::ascent() const QFixed QFontEngineFT::descent() const { - return QFixed::fromFixed(-metrics.descender); + // subtract a pixel to work around QFontMetrics's built-in + 1 + return QFixed::fromFixed(-metrics.descender - 64); } QFixed QFontEngineFT::leading() const diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 8ce437d..a4e7c04 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -546,7 +546,7 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); for (int i = 0; i < nGlyphs; ++i) { diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp index ef3f2ae..94974fc 100644 --- a/src/gui/text/qfontengine_qpf.cpp +++ b/src/gui/text/qfontengine_qpf.cpp @@ -819,7 +819,7 @@ FT_Face QFontEngineQPF::lockFace() const FT_Face face = freetype->face; // ### not perfect - const int ysize = fontDef.pixelSize << 6; + const int ysize = qRound(fontDef.pixelSize * qreal(64)); const int xsize = ysize; if (freetype->xsize != xsize || freetype->ysize != ysize) { diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index cc555a3..6c367ab 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -125,6 +125,7 @@ HDC shared_dc() } #endif +#ifndef Q_WS_WINCE typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT); static PtrGetCharWidthI ptrGetCharWidthI = 0; static bool resolvedGetCharWidthI = false; @@ -136,6 +137,7 @@ static void resolveGetCharWidthI() resolvedGetCharWidthI = true; ptrGetCharWidthI = (PtrGetCharWidthI)QLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI"); } +#endif // !defined(Q_WS_WINCE) // defined in qtextengine_win.cpp typedef void *SCRIPT_CACHE; @@ -206,7 +208,7 @@ void QFontEngineWin::getCMap() unitsPerEm = otm->otmEMSquare; x_height = (int)otm->otmsXHeight; loadKerningPairs(designToDevice); - _faceId.filename = (char *)otm + (int)otm->otmpFullName; + _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFullName)).toLatin1(); lineWidth = otm->otmsUnderscoreSize; fsType = otm->otmfsType; free(otm); @@ -340,8 +342,10 @@ QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont designAdvances = 0; designAdvancesSize = 0; +#ifndef Q_WS_WINCE if (!resolvedGetCharWidthI) resolveGetCharWidthI(); +#endif } QFontEngineWin::~QFontEngineWin() @@ -381,80 +385,18 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph if (flags & QTextEngine::GlyphIndicesOnly) return true; -#if defined(Q_WS_WINCE) - HDC hdc = shared_dc(); - if (flags & QTextEngine::DesignMetrics) { - HGDIOBJ oldFont = 0; - int glyph_pos = 0; - for(register int i = 0; i < len; i++) { - bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1 - && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000); - unsigned int glyph = glyphs->glyphs[glyph_pos]; - if(int(glyph) >= designAdvancesSize) { - int newSize = (glyph + 256) >> 8 << 8; - designAdvances = q_check_ptr((QFixed *)realloc(designAdvances, newSize*sizeof(QFixed))); - for(int i = designAdvancesSize; i < newSize; ++i) - designAdvances[i] = -1000000; - designAdvancesSize = newSize; - } - if(designAdvances[glyph] < -999999) { - if(!oldFont) - oldFont = selectDesignFont(); - SIZE size = {0, 0}; - GetTextExtentPoint32(hdc, (wchar_t *)(str+i), surrogate ? 2 : 1, &size); - designAdvances[glyph] = QFixed((int)size.cx)/designToDevice; - } - glyphs->advances_x[glyph_pos] = designAdvances[glyph]; - glyphs->advances_y[glyph_pos] = 0; - if (surrogate) - ++i; - ++glyph_pos; - } - if(oldFont) - DeleteObject(SelectObject(hdc, oldFont)); - } else { - int glyph_pos = 0; - HGDIOBJ oldFont = 0; - - for(register int i = 0; i < len; i++) { - bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1 - && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000); - unsigned int glyph = glyphs->glyphs[glyph_pos]; - - glyphs->advances_y[glyph_pos] = 0; - - if (glyph >= widthCacheSize) { - int newSize = (glyph + 256) >> 8 << 8; - widthCache = q_check_ptr((unsigned char *)realloc(widthCache, - newSize*sizeof(QFixed))); - memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize); - widthCacheSize = newSize; - } - glyphs->advances_x[glyph_pos] = widthCache[glyph]; - // font-width cache failed - if (glyphs->advances_x[glyph_pos] == 0) { - SIZE size = {0, 0}; - if (!oldFont) - oldFont = SelectObject(hdc, hfont); - GetTextExtentPoint32(hdc, (wchar_t *)str + i, surrogate ? 2 : 1, &size); - glyphs->advances_x[glyph_pos] = size.cx; - // if glyph's within cache range, store it for later - if (size.cx > 0 && size.cx < 0x100) - widthCache[glyph] = size.cx; - } - - if (surrogate) - ++i; - ++glyph_pos; - } + recalcAdvances(glyphs, flags); + return true; +} - if (oldFont) - SelectObject(hdc, oldFont); - } +inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width) +{ +#if defined(Q_WS_WINCE) + GetCharWidth32(hdc, glyph, glyph, &width); #else - recalcAdvances(glyphs, flags); + if (ptrGetCharWidthI) + ptrGetCharWidthI(hdc, glyph, 1, 0, &width); #endif - return true; } void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const @@ -477,8 +419,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla oldFont = selectDesignFont(); int width = 0; - if (ptrGetCharWidthI) - ptrGetCharWidthI(hdc, glyph, 1, 0, &width); + calculateTTFGlyphWidth(hdc, glyph, width); designAdvances[glyph] = QFixed(width) / designToDevice; } glyphs->advances_x[i] = designAdvances[glyph]; @@ -517,8 +458,8 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla SIZE size = {0, 0}; GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size); width = size.cx; - } else if (ptrGetCharWidthI) { - ptrGetCharWidthI(hdc, glyph, 1, 0, &width); + } else { + calculateTTFGlyphWidth(hdc, glyph, width); } glyphs->advances_x[i] = width; // if glyph's within cache range, store it for later @@ -636,7 +577,9 @@ QFixed QFontEngineWin::ascent() const QFixed QFontEngineWin::descent() const { - return tm.tmDescent; + // ### we substract 1 to even out the historical +1 in QFontMetrics's + // ### height=asc+desc+1 equation. Fix in Qt5. + return tm.tmDescent - 1; } QFixed QFontEngineWin::leading() const @@ -1044,8 +987,8 @@ QFontEngine::Properties QFontEngineWin::properties() const Properties p; p.emSquare = unitsPerEm; p.italicAngle = otm->otmItalicAngle; - p.postscriptName = (char *)otm + (int)otm->otmpFamilyName; - p.postscriptName += (char *)otm + (int)otm->otmpStyleName; + p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpFamilyName)).toLatin1(); + p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (int)otm->otmpStyleName)).toLatin1(); #ifndef QT_NO_PRINTER p.postscriptName = QPdf::stripSpecialCharacters(p.postscriptName); #endif @@ -1167,7 +1110,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin ih + 2 * margin + 4, QNativeImage::systemFormat(), !qt_cleartype_enabled); - /*If cleartype is enabled we use the standard system format even on Windows CE + /*If cleartype is enabled we use the standard system format even on Windows CE and not the special textbuffer format we have to use if cleartype is disabled*/ ni->image.fill(0xffffffff); diff --git a/src/gui/text/qfontinfo.h b/src/gui/text/qfontinfo.h index 335d761..0998949 100644 --- a/src/gui/text/qfontinfo.h +++ b/src/gui/text/qfontinfo.h @@ -43,6 +43,7 @@ #define QFONTINFO_H #include <QtGui/qfont.h> +#include <QtCore/qsharedpointer.h> QT_BEGIN_HEADER @@ -77,7 +78,7 @@ public: bool exactMatch() const; private: - QFontPrivate *d; + QExplicitlySharedDataPointer<QFontPrivate> d; }; QT_END_NAMESPACE diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index ce122aa..b8c1b33 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -165,7 +165,6 @@ extern int qt_defaultDpi(); QFontMetrics::QFontMetrics(const QFont &font) : d(font.d.data()) { - d->ref.ref(); } /*! @@ -196,7 +195,6 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice) d->screen = screen; } else { d = font.d.data(); - d->ref.ref(); } } @@ -205,8 +203,9 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice) Constructs a copy of \a fm. */ QFontMetrics::QFontMetrics(const QFontMetrics &fm) - : d(fm.d) -{ d->ref.ref(); } + : d(fm.d.data()) +{ +} /*! Destroys the font metrics object and frees all allocated @@ -214,8 +213,6 @@ QFontMetrics::QFontMetrics(const QFontMetrics &fm) */ QFontMetrics::~QFontMetrics() { - if (!d->ref.deref()) - delete d; } /*! @@ -223,7 +220,7 @@ QFontMetrics::~QFontMetrics() */ QFontMetrics &QFontMetrics::operator=(const QFontMetrics &fm) { - qAtomicAssign(d, fm.d); + d = fm.d.data(); return *this; } @@ -536,7 +533,7 @@ int QFontMetrics::width(const QString &text, int len) const if (len == 0) return 0; - QTextEngine layout(text, d); + QTextEngine layout(text, d.data()); layout.ignoreBidi = true; return qRound(layout.width(0, len)); } @@ -612,7 +609,7 @@ int QFontMetrics::charWidth(const QString &text, int pos) const int from = qMax(0, pos - 8); int to = qMin(text.length(), pos + 8); QString cstr = QString::fromRawData(text.unicode() + from, to - from); - QTextEngine layout(cstr, d); + QTextEngine layout(cstr, d.data()); layout.ignoreBidi = true; layout.itemize(); width = qRound(layout.width(pos-from, 1)); @@ -661,7 +658,7 @@ QRect QFontMetrics::boundingRect(const QString &text) const if (text.length() == 0) return QRect(); - QTextEngine layout(text, d); + QTextEngine layout(text, d.data()); layout.ignoreBidi = true; layout.itemize(); glyph_metrics_t gm = layout.boundingBox(0, text.length()); @@ -770,7 +767,7 @@ QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &te QRectF rb; QRectF rr(rect); - qt_format_text(QFont(d), rr, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray, + qt_format_text(QFont(d.data()), rr, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray, tabArrayLen, 0); return rb.toAlignedRect(); @@ -831,7 +828,7 @@ QRect QFontMetrics::tightBoundingRect(const QString &text) const if (text.length() == 0) return QRect(); - QTextEngine layout(text, d); + QTextEngine layout(text, d.data()); layout.ignoreBidi = true; layout.itemize(); glyph_metrics_t gm = layout.tightBoundingBox(0, text.length()); @@ -876,7 +873,7 @@ QString QFontMetrics::elidedText(const QString &text, Qt::TextElideMode mode, in } _text = _text.mid(posA); } - QStackTextEngine engine(_text, QFont(d)); + QStackTextEngine engine(_text, QFont(d.data())); return engine.elidedText(mode, width, flags); } @@ -989,9 +986,8 @@ int QFontMetrics::lineWidth() const from the given \a fontMetrics object. */ QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics) - : d(fontMetrics.d) + : d(fontMetrics.d.data()) { - d->ref.ref(); } /*! @@ -1001,7 +997,7 @@ QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics) */ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other) { - qAtomicAssign(d, other.d); + d = other.d.data(); return *this; } @@ -1021,7 +1017,6 @@ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other) QFontMetricsF::QFontMetricsF(const QFont &font) : d(font.d.data()) { - d->ref.ref(); } /*! @@ -1052,7 +1047,6 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice) d->screen = screen; } else { d = font.d.data(); - d->ref.ref(); } } @@ -1061,8 +1055,9 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice) Constructs a copy of \a fm. */ QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm) - : d(fm.d) -{ d->ref.ref(); } + : d(fm.d.data()) +{ +} /*! Destroys the font metrics object and frees all allocated @@ -1070,8 +1065,6 @@ QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm) */ QFontMetricsF::~QFontMetricsF() { - if (!d->ref.deref()) - delete d; } /*! @@ -1079,7 +1072,7 @@ QFontMetricsF::~QFontMetricsF() */ QFontMetricsF &QFontMetricsF::operator=(const QFontMetricsF &fm) { - qAtomicAssign(d, fm.d); + d = fm.d.data(); return *this; } @@ -1374,7 +1367,7 @@ qreal QFontMetricsF::rightBearing(QChar ch) const */ qreal QFontMetricsF::width(const QString &text) const { - QTextEngine layout(text, d); + QTextEngine layout(text, d.data()); layout.ignoreBidi = true; layout.itemize(); return layout.width(0, text.length()).toReal(); @@ -1451,7 +1444,7 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const if (len == 0) return QRectF(); - QTextEngine layout(text, d); + QTextEngine layout(text, d.data()); layout.ignoreBidi = true; layout.itemize(); glyph_metrics_t gm = layout.boundingBox(0, len); @@ -1559,7 +1552,7 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& tabArrayLen++; QRectF rb; - qt_format_text(QFont(d), rect, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray, + qt_format_text(QFont(d.data()), rect, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray, tabArrayLen, 0); return rb; } @@ -1624,7 +1617,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const if (text.length() == 0) return QRect(); - QTextEngine layout(text, d); + QTextEngine layout(text, d.data()); layout.ignoreBidi = true; layout.itemize(); glyph_metrics_t gm = layout.tightBoundingBox(0, text.length()); @@ -1649,7 +1642,7 @@ QRectF QFontMetricsF::tightBoundingRect(const QString &text) const */ QString QFontMetricsF::elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags) const { - QStackTextEngine engine(text, QFont(d)); + QStackTextEngine engine(text, QFont(d.data())); return engine.elidedText(mode, QFixed::fromReal(width), flags); } diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 1147e3a..23200c5 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -43,6 +43,7 @@ #define QFONTMETRICS_H #include <QtGui/qfont.h> +#include <QtCore/qsharedpointer.h> #ifndef QT_INCLUDE_COMPAT #include <QtCore/qrect.h> #endif @@ -131,7 +132,7 @@ private: friend class QFontMetricsF; friend class QStackTextEngine; - QFontPrivate *d; + QExplicitlySharedDataPointer<QFontPrivate> d; }; @@ -187,7 +188,7 @@ public: inline bool operator !=(const QFontMetricsF &other) const { return !operator==(other); } private: - QFontPrivate *d; + QExplicitlySharedDataPointer<QFontPrivate> d; }; QT_END_NAMESPACE diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index ee8b751..3f6545c 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1619,9 +1619,11 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF if (cursor.position() != oldCursorPos) emit q->cursorPositionChanged(); _q_updateCurrentCharFormatAndSelection(); +#ifndef QT_NO_IM if (QInputContext *ic = inputContext()) { ic->update(); } +#endif //QT_NO_IM } else { //emit q->visibilityRequest(QRectF(mousePos, QSizeF(1, 1))); if (cursor.position() != oldCursorPos) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index a8956b8..1aad385 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -140,7 +140,7 @@ bool Qt::mightBeRichText(const QString& text) /*! Converts the plain text string \a plain to a HTML string with - HTML metacharacters \c{<}, \c{>}, and \c{&} replaced by HTML + HTML metacharacters \c{<}, \c{>}, \c{&}, and \c{"} replaced by HTML entities. Example: @@ -162,6 +162,8 @@ QString Qt::escape(const QString& plain) rich += QLatin1String(">"); else if (plain.at(i) == QLatin1Char('&')) rich += QLatin1String("&"); + else if (plain.at(i) == QLatin1Char('"')) + rich += QLatin1String("""); else rich += plain.at(i); } @@ -956,6 +958,8 @@ QString QTextDocument::defaultStyleSheet() const /*! Returns true if undo is available; otherwise returns false. + + \sa isRedoAvailable(), availableUndoSteps() */ bool QTextDocument::isUndoAvailable() const { @@ -965,6 +969,8 @@ bool QTextDocument::isUndoAvailable() const /*! Returns true if redo is available; otherwise returns false. + + \sa isUndoAvailable(), availableRedoSteps() */ bool QTextDocument::isRedoAvailable() const { @@ -972,6 +978,29 @@ bool QTextDocument::isRedoAvailable() const return d->isRedoAvailable(); } +/*! \since 4.6 + + Returns the number of available undo steps. + + \sa isUndoAvailable() +*/ +int QTextDocument::availableUndoSteps() const +{ + Q_D(const QTextDocument); + return d->availableUndoSteps(); +} + +/*! \since 4.6 + + Returns the number of available redo steps. + + \sa isRedoAvailable() +*/ +int QTextDocument::availableRedoSteps() const +{ + Q_D(const QTextDocument); + return d->availableRedoSteps(); +} /*! \since 4.4 @@ -2038,7 +2067,7 @@ void QTextHtmlExporter::emitAttribute(const char *attribute, const QString &valu html += QLatin1Char(' '); html += QLatin1String(attribute); html += QLatin1String("=\""); - html += value; + html += Qt::escape(value); html += QLatin1Char('"'); } @@ -2302,12 +2331,12 @@ void QTextHtmlExporter::emitFontFamily(const QString &family) { html += QLatin1String(" font-family:"); - QLatin1Char quote('\''); - if (family.contains(quote)) - quote = QLatin1Char('\"'); + QLatin1String quote("\'"); + if (family.contains(QLatin1Char('\''))) + quote = QLatin1String("""); html += quote; - html += family; + html += Qt::escape(family); html += quote; html += QLatin1Char(';'); } @@ -2341,13 +2370,13 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment) const QString name = format.anchorName(); if (!name.isEmpty()) { html += QLatin1String("<a name=\""); - html += name; + html += Qt::escape(name); html += QLatin1String("\"></a>"); } const QString href = format.anchorHref(); if (!href.isEmpty()) { html += QLatin1String("<a href=\""); - html += href; + html += Qt::escape(href); html += QLatin1String("\">"); closeAnchor = true; } diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index e52716a..d217a4d 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -142,6 +142,9 @@ public: bool isUndoAvailable() const; bool isRedoAvailable() const; + int availableUndoSteps() const; + int availableRedoSteps() const; + int revision() const; void setDocumentLayout(QAbstractTextDocumentLayout *layout); diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index ce25c57..c10855b 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -212,6 +212,9 @@ public: inline bool isUndoAvailable() const { return undoEnabled && undoState > 0; } inline bool isRedoAvailable() const { return undoEnabled && undoState < undoStack.size(); } + inline int availableUndoSteps() const { return undoEnabled ? undoState : 0; } + inline int availableRedoSteps() const { return undoEnabled ? qMax(undoStack.size() - undoState - 1, 0) : 0; } + inline QString buffer() const { return text; } QString plainText() const; inline int length() const { return fragments.length(); } diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index de83d39..73434b1 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -1437,7 +1437,9 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p option.setTextDirection(dir); layout.setTextOption(option); layout.beginLayout(); - layout.createLine(); + QTextLine line = layout.createLine(); + if (line.isValid()) + line.setLeadingIncluded(true); layout.endLayout(); layout.draw(painter, QPointF(r.left(), pos.y())); break; @@ -2579,6 +2581,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi QTextLine line = tl->createLine(); if (!line.isValid()) break; + line.setLeadingIncluded(true); QFixed left, right; floatMargins(layoutStruct->y, layoutStruct, &left, &right); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 81c9142..a91408f 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1042,7 +1042,7 @@ void QTextEngine::shapeTextWithCE(int item) const QScriptItem &si = layoutData->items[item]; si.glyph_data_offset = layoutData->used; - QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent); + QFontEngine *fe = fontEngine(si, &si.ascent, &si.descent, &si.leading); QTextEngine::ShaperFlags flags; if (si.analysis.bidiLevel % 2) @@ -1119,7 +1119,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const si.glyph_data_offset = layoutData->used; - QFontEngine *font = fontEngine(si, &si.ascent, &si.descent); + QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); bool kerningEnabled = this->font(si).d->kerning; @@ -1350,8 +1350,11 @@ void QTextEngine::shape(int item) const layoutData->items[item].position + block.position(), format); } } else if (layoutData->items[item].analysis.flags == QScriptAnalysis::Tab) { - // set up at least the ascent/descent of the script item for the tab - fontEngine(layoutData->items[item], &layoutData->items[item].ascent, &layoutData->items[item].descent); + // set up at least the ascent/descent/leading of the script item for the tab + fontEngine(layoutData->items[item], + &layoutData->items[item].ascent, + &layoutData->items[item].descent, + &layoutData->items[item].leading); } else { shapeText(item); } @@ -1737,7 +1740,7 @@ QFont QTextEngine::font(const QScriptItem &si) const return font; } -QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent) const +QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFixed *descent, QFixed *leading) const { QFontEngine *engine = 0; QFontEngine *scaledEngine = 0; @@ -1777,6 +1780,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix if (ascent) { *ascent = engine->ascent(); *descent = engine->descent(); + *leading = engine->leading(); } if (scaledEngine) @@ -2009,8 +2013,12 @@ void QScriptLine::setDefaultHeight(QTextEngine *eng) e = eng->fnt.d->engineForScript(QUnicodeTables::Common); } - ascent = qMax(ascent, e->ascent()); - descent = qMax(descent, e->descent()); + QFixed other_ascent = e->ascent(); + QFixed other_descent = e->descent(); + QFixed other_leading = e->leading(); + leading = qMax(leading + ascent, other_leading + other_ascent) - qMax(ascent, other_ascent); + ascent = qMax(ascent, other_ascent); + descent = qMax(descent, other_descent); } QTextEngine::LayoutData::LayoutData() diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp index e101830..54be53b 100644 --- a/src/gui/text/qtextengine_mac.cpp +++ b/src/gui/text/qtextengine_mac.cpp @@ -557,7 +557,7 @@ void QTextEngine::shapeTextMac(int item) const si.glyph_data_offset = layoutData->used; - QFontEngine *font = fontEngine(si, &si.ascent, &si.descent); + QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); if (font->type() != QFontEngine::Multi) { shapeTextWithHarfbuzz(item); return; @@ -594,53 +594,50 @@ void QTextEngine::shapeTextMac(int item) const str = reinterpret_cast<const QChar *>(uc); } - while (true) { - ensureSpace(num_glyphs); - num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used; - - QGlyphLayout g = availableGlyphs(&si); - g.numGlyphs = num_glyphs; - unsigned short *log_clusters = logClusters(&si); + ensureSpace(num_glyphs); + num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used; - if (fe->stringToCMap(str, - len, - &g, - &num_glyphs, - flags, - log_clusters, - attributes())) { + QGlyphLayout g = availableGlyphs(&si); + g.numGlyphs = num_glyphs; + unsigned short *log_clusters = logClusters(&si); - heuristicSetGlyphAttributes(str, len, &g, log_clusters, num_glyphs); - break; - } + bool stringToCMapFailed = false; + if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes())) { + ensureSpace(num_glyphs); + stringToCMapFailed = fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, + attributes()); } - si.num_glyphs = num_glyphs; + if (!stringToCMapFailed) { + heuristicSetGlyphAttributes(str, len, &g, log_clusters, num_glyphs); - layoutData->used += si.num_glyphs; + si.num_glyphs = num_glyphs; - QGlyphLayout g = shapedGlyphs(&si); + layoutData->used += si.num_glyphs; - if (si.analysis.script == QUnicodeTables::Arabic) { - QVarLengthArray<QArabicProperties> props(len + 2); - QArabicProperties *properties = props.data(); - int f = si.position; - int l = len; - if (f > 0) { - --f; - ++l; - ++properties; - } - if (f + l < layoutData->string.length()) { - ++l; - } - qt_getArabicProperties((const unsigned short *)(layoutData->string.unicode()+f), l, props.data()); + QGlyphLayout g = shapedGlyphs(&si); - unsigned short *log_clusters = logClusters(&si); + if (si.analysis.script == QUnicodeTables::Arabic) { + QVarLengthArray<QArabicProperties> props(len + 2); + QArabicProperties *properties = props.data(); + int f = si.position; + int l = len; + if (f > 0) { + --f; + ++l; + ++properties; + } + if (f + l < layoutData->string.length()) { + ++l; + } + qt_getArabicProperties((const unsigned short *)(layoutData->string.unicode()+f), l, props.data()); - for (int i = 0; i < len; ++i) { - int gpos = log_clusters[i]; - g.attributes[gpos].justification = properties[i].justification; + unsigned short *log_clusters = logClusters(&si); + + for (int i = 0; i < len; ++i) { + int gpos = log_clusters[i]; + g.attributes[gpos].justification = properties[i].justification; + } } } diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 85c6928..a1d363b 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -345,11 +345,11 @@ struct Q_AUTOTEST_EXPORT QScriptItem { inline QScriptItem() : position(0), - num_glyphs(0), descent(-1), ascent(-1), width(-1), + num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1), glyph_data_offset(0) {} inline QScriptItem(int p, const QScriptAnalysis &a) : position(p), analysis(a), - num_glyphs(0), descent(-1), ascent(-1), width(-1), + num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1), glyph_data_offset(0) {} int position; @@ -357,6 +357,7 @@ struct Q_AUTOTEST_EXPORT QScriptItem unsigned short num_glyphs; QFixed descent; QFixed ascent; + QFixed leading; QFixed width; int glyph_data_offset; QFixed height() const { return ascent + descent + 1; } @@ -373,9 +374,10 @@ struct Q_AUTOTEST_EXPORT QScriptLine QScriptLine() : from(0), length(0), justified(0), gridfitted(0), - hasTrailingSpaces(0) {} + hasTrailingSpaces(0), leadingIncluded(0) {} QFixed descent; QFixed ascent; + QFixed leading; QFixed x; QFixed y; QFixed width; @@ -385,7 +387,11 @@ struct Q_AUTOTEST_EXPORT QScriptLine mutable uint justified : 1; mutable uint gridfitted : 1; uint hasTrailingSpaces : 1; - QFixed height() const { return ascent + descent + 1; } + uint leadingIncluded : 1; + QFixed height() const { return ascent + descent + 1 + + (leadingIncluded? qMax(QFixed(),leading) : QFixed()); } + QFixed base() const { return ascent + + (leadingIncluded ? qMax(QFixed(),leading) : QFixed()); } void setDefaultHeight(QTextEngine *eng); void operator+=(const QScriptLine &other); }; @@ -394,6 +400,7 @@ Q_DECLARE_TYPEINFO(QScriptLine, Q_PRIMITIVE_TYPE); inline void QScriptLine::operator+=(const QScriptLine &other) { + leading= qMax(leading + ascent, other.leading + other.ascent) - qMax(ascent, other.ascent); descent = qMax(descent, other.descent); ascent = qMax(ascent, other.ascent); textWidth += other.textWidth; @@ -476,7 +483,7 @@ public: return end - si->position; } - QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = 0, QFixed *descent = 0) const; + QFontEngine *fontEngine(const QScriptItem &si, QFixed *ascent = 0, QFixed *descent = 0, QFixed *leading = 0) const; QFont font(const QScriptItem &si) const; inline QFont font() const { return fnt; } diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index c5f0e35..4600a29 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -860,7 +860,7 @@ QRectF QTextLayout::boundingRect() const ymin = qMin(ymin, si.y); xmax = qMax(xmax, si.x+qMax(si.width, si.textWidth)); // ### shouldn't the ascent be used in ymin??? - ymax = qMax(ymax, si.y+si.ascent+si.descent+1); + ymax = qMax(ymax, si.y+si.height()); } return QRectF(xmin.toReal(), ymin.toReal(), (xmax-xmin).toReal(), (ymax-ymin).toReal()); } @@ -1071,10 +1071,10 @@ static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPo QTextLineItemIterator iterator(eng, lineNumber, pos, selection); - const QFixed y = QFixed::fromReal(pos.y()) + line.y + line.ascent; + + const qreal selectionY = pos.y() + line.y.toReal(); const qreal lineHeight = line.height().toReal(); - const qreal selectionY = (y - line.ascent).toReal(); QFixed lastSelectionX = iterator.x; QFixed lastSelectionWidth; @@ -1334,23 +1334,23 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition const qreal x = position.x() + l.cursorToX(cursorPosition); int itm = d->findItem(cursorPosition - 1); - QFixed ascent = sl.ascent; + QFixed base = sl.base(); QFixed descent = sl.descent; bool rightToLeft = (d->option.textDirection() == Qt::RightToLeft); if (itm >= 0) { const QScriptItem &si = d->layoutData->items.at(itm); if (si.ascent > 0) - ascent = si.ascent; + base = si.ascent; if (si.descent > 0) descent = si.descent; rightToLeft = si.analysis.bidiLevel % 2; } - qreal y = position.y() + (sl.y + sl.ascent - ascent).toReal(); + qreal y = position.y() + (sl.y + sl.base() - base).toReal(); bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing) && (p->transform().type() > QTransform::TxTranslate); if (toggleAntialiasing) p->setRenderHint(QPainter::Antialiasing); - p->fillRect(QRectF(x, y, qreal(width), (ascent + descent).toReal()), p->pen().brush()); + p->fillRect(QRectF(x, y, qreal(width), (base + descent + 1).toReal()), p->pen().brush()); if (toggleAntialiasing) p->setRenderHint(QPainter::Antialiasing, false); if (d->layoutData->hasBidi) { @@ -1500,9 +1500,11 @@ qreal QTextLine::descent() const } /*! - Returns the line's height. This is equal to ascent() + descent() + 1. + Returns the line's height. This is equal to ascent() + descent() + 1 + if leading is not included. If leading is included, this equals to + ascent() + descent() + leading() + 1. - \sa ascent() descent() + \sa ascent() descent() leading() setLeadingIncluded() */ qreal QTextLine::height() const { @@ -1510,6 +1512,51 @@ qreal QTextLine::height() const } /*! + \since 4.6 + + Returns the line's leading. + + \sa ascent() descent() height() +*/ +qreal QTextLine::leading() const +{ + return eng->lines[i].leading.toReal(); +} + +/*! \since 4.6 + + Includes positive leading into the line's height if \a included is true; + otherwise does not include leading. + + By default, leading is not included. + + Note that negative leading is ignored, it must be handled + in the code using the text lines by letting the lines overlap. + + \sa leadingIncluded() + +*/ +void QTextLine::setLeadingIncluded(bool included) +{ + eng->lines[i].leadingIncluded= included; + +} + +/*! \since 4.6 + + Returns true if positive leading is included into the line's height; otherwise returns false. + + By default, leading is not included. + + \sa setLeadingIncluded() +*/ +bool QTextLine::leadingIncluded() const +{ + return eng->lines[i].leadingIncluded; +} + + +/*! Returns the width of the line that is occupied by text. This is always \<= to width(), and is the minimum width that could be used by layout() without changing the line break position. @@ -1712,6 +1759,9 @@ void QTextLine::layout_helper(int maxGlyphs) } const QScriptItem ¤t = eng->layoutData->items[item]; + lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, + current.leading + current.ascent) - qMax(lbh.tmpData.ascent, + current.ascent); lbh.tmpData.ascent = qMax(lbh.tmpData.ascent, current.ascent); lbh.tmpData.descent = qMax(lbh.tmpData.descent, current.descent); @@ -2042,7 +2092,9 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR QTextLineItemIterator iterator(eng, i, pos, selection); - const QFixed y = QFixed::fromReal(pos.y()) + line.y + line.ascent; + QFixed lineBase = line.base(); + + const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase; bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors); while (!iterator.atEnd()) { @@ -2065,7 +2117,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR if (selection) format.merge(selection->format); - setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - line.ascent).toReal(), + setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(), iterator.itemWidth.toReal(), line.height().toReal())); QTextCharFormat::VerticalAlignment valign = format.verticalAlignment(); @@ -2086,7 +2138,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR if (si.analysis.flags == QScriptAnalysis::Object && eng->block.docHandle()) { QFixed itemY = y - si.ascent; if (format.verticalAlignment() == QTextCharFormat::AlignTop) { - itemY = y - line.ascent; + itemY = y - lineBase; } QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal()); diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index 90afac8..9f170f5 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -196,6 +196,10 @@ public: qreal ascent() const; qreal descent() const; qreal height() const; + qreal leading() const; + + void setLeadingIncluded(bool included); + bool leadingIncluded() const; qreal naturalTextWidth() const; QRectF naturalTextRect() const; diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index b28ecd7..b7615a4 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -78,6 +78,7 @@ win32 { unix:x11 { HEADERS += \ text/qfontengine_x11_p.h \ + text/qfontdatabase_x11.cpp \ text/qfontengine_ft_p.h SOURCES += \ text/qfont_x11.cpp \ diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp index 588a48e..fec9fab 100644 --- a/src/gui/widgets/qabstractslider.cpp +++ b/src/gui/widgets/qabstractslider.cpp @@ -693,29 +693,27 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e) if (e->orientation() != d->orientation && !rect().contains(e->pos())) return; - qreal currentOffset = qreal(e->delta()) / 120; - d->offset_accumulated += currentOffset; - if (int(d->offset_accumulated) == 0) { - // QAbstractSlider works on integer values. So if the accumulated - // offset is less than +/- 1, we need to wait until we get more - // wheel events (this means that the wheel resolution is higher than - // 15 degrees, e.g. when using mac mighty mouse/trackpad): - return; - } + int stepsToScroll = 0; + qreal offset = qreal(e->delta()) / 120; - int stepsToScroll; if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) { - stepsToScroll = currentOffset > 0 ? d->pageStep : -d->pageStep; + // Scroll one page regardless of delta: + stepsToScroll = qBound(-d->pageStep, int(offset * d->pageStep), d->pageStep); + d->offset_accumulated = 0; } else { - // Calculate the number of steps to scroll (per 15 degrees of rotate): -#ifdef Q_OS_MAC - // On mac, since mouse wheel scrolling is accelerated and - // fine tuned by the OS, we skip applying acceleration: - stepsToScroll = int(d->offset_accumulated); -#else - stepsToScroll = int(d->offset_accumulated) * QApplication::wheelScrollLines() * d->singleStep; -#endif - stepsToScroll = qBound(-d->pageStep, stepsToScroll, d->pageStep); + // Calculate how many lines to scroll. Depending on what delta is (and + // offset), we might end up with a fraction (e.g. scroll 1.3 lines). We can + // only scroll whole lines, so we keep the reminder until next event. + qreal stepsToScrollF = offset * QApplication::wheelScrollLines() * d->singleStep; + // Check if wheel changed direction since last event: + if (d->offset_accumulated != 0 && (offset / d->offset_accumulated) < 0) + d->offset_accumulated = 0; + + d->offset_accumulated += stepsToScrollF; + stepsToScroll = qBound(-d->pageStep, int(d->offset_accumulated), d->pageStep); + d->offset_accumulated -= int(d->offset_accumulated); + if (stepsToScroll == 0) + return; } if (d->invertedControls) @@ -725,12 +723,10 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e) d->position = d->overflowSafeAdd(stepsToScroll); // value will be updated by triggerAction() triggerAction(SliderMove); - if (prevValue == d->value) { + if (prevValue == d->value) d->offset_accumulated = 0; - } else { - d->offset_accumulated -= int(d->offset_accumulated); + else e->accept(); - } } #endif #ifdef QT_KEYPAD_NAVIGATION diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 0e888d6..1879db4 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -192,6 +192,8 @@ void QComboBoxPrivate::_q_modelReset() lineEdit->setText(QString()); updateLineEditGeometry(); } + if (currentIndex.row() != indexBeforeChange) + _q_emitCurrentIndexChanged(currentIndex); q->update(); } @@ -314,7 +316,7 @@ QSize QComboBoxPrivate::recomputeSizeHint(QSize &sh) const // height - sh.setHeight(qMax(fm.lineSpacing(), 14) + 2); + sh.setHeight(qMax(fm.height(), 14) + 2); if (hasIcon) { sh.setHeight(qMax(sh.height(), iconSize.height() + 2)); } @@ -402,13 +404,6 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView layout->setSpacing(0); layout->setMargin(0); -#ifdef QT_SOFTKEYS_ENABLED - selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, this); - cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, this); - addAction(selectAction); - addAction(cancelAction); -#endif - // set item view setItemView(itemView); @@ -494,18 +489,6 @@ void QComboBoxPrivateContainer::viewDestroyed() } /* - Sets currentIndex on entered if the LeftButton is not pressed. This - means that if mouseTracking(...) is on, we setCurrentIndex and select - even when LeftButton is not pressed. -*/ -void QComboBoxPrivateContainer::setCurrentIndex(const QModelIndex &index) -{ - if (QComboBoxDelegate::isSeparator(index)) - return; - view->setCurrentIndex(index); -} - -/* Returns the item view used for the combobox popup. */ QAbstractItemView *QComboBoxPrivateContainer::itemView() const @@ -530,8 +513,6 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) disconnect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(updateScrollers())); #endif - disconnect(view, SIGNAL(entered(QModelIndex)), - this, SLOT(setCurrentIndex(QModelIndex))); disconnect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); @@ -568,10 +549,15 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) connect(view->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(updateScrollers())); #endif - connect(view, SIGNAL(entered(QModelIndex)), - this, SLOT(setCurrentIndex(QModelIndex))); connect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); + +#ifdef QT_SOFTKEYS_ENABLED + selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, itemView); + cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, itemView); + addAction(selectAction); + addAction(cancelAction); +#endif } /*! @@ -653,16 +639,20 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) break; } break; - case QEvent::MouseMove: { + case QEvent::MouseMove: if (isVisible()) { QMouseEvent *m = static_cast<QMouseEvent *>(e); QWidget *widget = static_cast<QWidget *>(o); QPoint vector = widget->mapToGlobal(m->pos()) - initialClickPosition; if (vector.manhattanLength() > 9 && blockMouseReleaseTimer.isActive()) blockMouseReleaseTimer.stop(); + QModelIndex indexUnderMouse = view->indexAt(m->pos()); + if (indexUnderMouse.isValid() && indexUnderMouse != view->currentIndex() + && !QComboBoxDelegate::isSeparator(indexUnderMouse)) { + view->setCurrentIndex(indexUnderMouse); + } } break; - } case QEvent::MouseButtonRelease: { QMouseEvent *m = static_cast<QMouseEvent *>(e); if (isVisible() && view->rect().contains(m->pos()) && view->currentIndex().isValid() @@ -992,14 +982,6 @@ void QComboBoxPrivate::_q_dataChanged(const QModelIndex &topLeft, const QModelIn } } -void QComboBoxPrivate::_q_rowsAboutToBeInserted(const QModelIndex & parent, - int /*start*/, int /*end*/) -{ - if (parent != root) - return; - indexBeforeChange = currentIndex.row(); -} - void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int end) { Q_Q(QComboBox); @@ -1022,11 +1004,8 @@ void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int } } -void QComboBoxPrivate::_q_rowsAboutToBeRemoved(const QModelIndex &parent, int /*start*/, int /*end*/) +void QComboBoxPrivate::_q_updateIndexBeforeChange() { - if (parent != root) - return; - indexBeforeChange = currentIndex.row(); } @@ -1868,15 +1847,17 @@ void QComboBox::setModel(QAbstractItemModel *model) disconnect(d->model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(_q_dataChanged(QModelIndex,QModelIndex))); disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); + this, SLOT(_q_updateIndexBeforeChange())); disconnect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_q_rowsInserted(QModelIndex,int,int))); disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); + this, SLOT(_q_updateIndexBeforeChange())); disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); disconnect(d->model, SIGNAL(destroyed()), this, SLOT(_q_modelDestroyed())); + disconnect(d->model, SIGNAL(modelAboutToBeReset()), + this, SLOT(_q_updateIndexBeforeChange())); disconnect(d->model, SIGNAL(modelReset()), this, SLOT(_q_modelReset())); if (d->model->QObject::parent() == this) @@ -1888,15 +1869,17 @@ void QComboBox::setModel(QAbstractItemModel *model) connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(_q_dataChanged(QModelIndex,QModelIndex))); connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); + this, SLOT(_q_updateIndexBeforeChange())); connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_q_rowsInserted(QModelIndex,int,int))); connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); + this, SLOT(_q_updateIndexBeforeChange())); connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_rowsRemoved(QModelIndex,int,int))); connect(model, SIGNAL(destroyed()), this, SLOT(_q_modelDestroyed())); + connect(model, SIGNAL(modelAboutToBeReset()), + this, SLOT(_q_updateIndexBeforeChange())); connect(model, SIGNAL(modelReset()), this, SLOT(_q_modelReset())); @@ -2452,15 +2435,15 @@ void QComboBox::showPopup() #if defined(Q_WS_WIN) && !defined(QT_NO_EFFECTS) bool scrollDown = (listRect.topLeft() == below); - if (QApplication::isEffectEnabled(Qt::UI_AnimateCombo) + if (QApplication::isEffectEnabled(Qt::UI_AnimateCombo) && !style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this) && !window()->testAttribute(Qt::WA_DontShowOnScreen)) qScrollEffect(container, scrollDown ? QEffects::DownScroll : QEffects::UpScroll, 150); #endif // Don't disable updates on Mac OS X. Windows are displayed immediately on this platform, // which means that the window will be visible before the call to container->show() returns. -// If updates are disabled at this point we'll miss our chance at painting the popup -// menu before it's shown, causing flicker since the window then displays the standard gray +// If updates are disabled at this point we'll miss our chance at painting the popup +// menu before it's shown, causing flicker since the window then displays the standard gray // background. #ifndef Q_WS_MAC container->setUpdatesEnabled(false); diff --git a/src/gui/widgets/qcombobox.h b/src/gui/widgets/qcombobox.h index 6a85096..0652594 100644 --- a/src/gui/widgets/qcombobox.h +++ b/src/gui/widgets/qcombobox.h @@ -52,7 +52,6 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Gui) - #ifndef QT_NO_COMBOBOX class QAbstractItemView; @@ -308,9 +307,8 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_returnPressed()) Q_PRIVATE_SLOT(d_func(), void _q_resetButton()) Q_PRIVATE_SLOT(d_func(), void _q_dataChanged(const QModelIndex &, const QModelIndex &)) - Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex & parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_updateIndexBeforeChange()) Q_PRIVATE_SLOT(d_func(), void _q_rowsInserted(const QModelIndex & parent, int start, int end)) - Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_rowsRemoved(const QModelIndex & parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed()) Q_PRIVATE_SLOT(d_func(), void _q_modelReset()) diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h index f7458c4..fe42c47 100644 --- a/src/gui/widgets/qcombobox_p.h +++ b/src/gui/widgets/qcombobox_p.h @@ -231,7 +231,6 @@ public: public Q_SLOTS: void scrollItemView(int action); void updateScrollers(); - void setCurrentIndex(const QModelIndex &index); void viewDestroyed(); protected: @@ -357,9 +356,8 @@ public: #endif void _q_resetButton(); void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); - void _q_rowsAboutToBeInserted(const QModelIndex & parent, int start, int end); + void _q_updateIndexBeforeChange(); void _q_rowsInserted(const QModelIndex & parent, int start, int end); - void _q_rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end); void _q_rowsRemoved(const QModelIndex & parent, int start, int end); void updateArrow(QStyle::StateFlag state); bool updateHoverControl(const QPoint &pos); diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index 5a0a9d4..dffec11 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -1556,9 +1556,10 @@ void QDockAreaLayoutInfo::apply(bool animate) } } } - +#ifndef QT_NO_TABBAR if (sep == 1) updateSeparatorWidgets(); +#endif //QT_NO_TABBAR } static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over) @@ -2008,13 +2009,14 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> updateTabBar(); setCurrentTabId(tabId(item_list.at(index))); } -#endif if (!testing && sep == 1) updateSeparatorWidgets(); +#endif return true; } +#ifndef QT_NO_TABBAR void QDockAreaLayoutInfo::updateSeparatorWidgets() const { if (tabbed) { @@ -2065,6 +2067,7 @@ void QDockAreaLayoutInfo::updateSeparatorWidgets() const separatorWidgets.resize(j); Q_ASSERT(separatorWidgets.size() == j); } +#endif //QT_NO_TABBAR #ifndef QT_NO_TABBAR void QDockAreaLayoutInfo::updateTabBar() const @@ -2259,7 +2262,7 @@ QRect QDockAreaLayoutInfo::tabContentRect() const ** QDockAreaLayout */ -QDockAreaLayout::QDockAreaLayout(QMainWindow *win) +QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true) { mainWindow = win; sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, win); @@ -2346,6 +2349,9 @@ bool QDockAreaLayout::restoreState(QDataStream &stream, const QList<QDockWidget* for (int i = 0; i < 4; ++i) corners[i] = static_cast<Qt::DockWidgetArea>(cornerData[i]); } + + if (!testing) + fallbackToSizeHints = false; } return ok; @@ -2582,7 +2588,7 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list, { QSize center_hint(0, 0); QSize center_min(0, 0); - bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty(); + const bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty(); if (have_central) { center_hint = centralWidgetRect.size(); if (!center_hint.isValid()) @@ -2601,33 +2607,35 @@ void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list, center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep); QSize left_hint = docks[QInternal::LeftDock].size(); - if (left_hint.isNull()) + if (left_hint.isNull() || fallbackToSizeHints) left_hint = docks[QInternal::LeftDock].sizeHint(); QSize left_min = docks[QInternal::LeftDock].minimumSize(); QSize left_max = docks[QInternal::LeftDock].maximumSize(); left_hint = left_hint.boundedTo(left_max).expandedTo(left_min); QSize right_hint = docks[QInternal::RightDock].size(); - if (right_hint.isNull()) + if (right_hint.isNull() || fallbackToSizeHints) right_hint = docks[QInternal::RightDock].sizeHint(); QSize right_min = docks[QInternal::RightDock].minimumSize(); QSize right_max = docks[QInternal::RightDock].maximumSize(); right_hint = right_hint.boundedTo(right_max).expandedTo(right_min); QSize top_hint = docks[QInternal::TopDock].size(); - if (top_hint.isNull()) + if (top_hint.isNull() || fallbackToSizeHints) top_hint = docks[QInternal::TopDock].sizeHint(); QSize top_min = docks[QInternal::TopDock].minimumSize(); QSize top_max = docks[QInternal::TopDock].maximumSize(); top_hint = top_hint.boundedTo(top_max).expandedTo(top_min); QSize bottom_hint = docks[QInternal::BottomDock].size(); - if (bottom_hint.isNull()) + if (bottom_hint.isNull() || fallbackToSizeHints) bottom_hint = docks[QInternal::BottomDock].sizeHint(); QSize bottom_min = docks[QInternal::BottomDock].minimumSize(); QSize bottom_max = docks[QInternal::BottomDock].maximumSize(); bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min); + fallbackToSizeHints = !have_central; + if (_ver_struct_list != 0) { QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list; ver_struct_list.resize(3); @@ -3073,9 +3081,10 @@ void QDockAreaLayout::apply(bool animate) widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animate); } - +#ifndef QT_NO_TABBAR if (sep == 1) updateSeparatorWidgets(); +#endif //QT_NO_TABBAR } void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget, @@ -3153,6 +3162,7 @@ int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &or return delta; } +#ifndef QT_NO_TABBAR // Sets the correct positions for the seperator widgets // Allocates new sepearator widgets with getSeparatorWidget void QDockAreaLayout::updateSeparatorWidgets() const @@ -3186,6 +3196,7 @@ void QDockAreaLayout::updateSeparatorWidgets() const separatorWidgets.resize(j); } +#endif //QT_NO_TABBAR QLayoutItem *QDockAreaLayout::itemAt(int *x, int index) const { @@ -3238,7 +3249,6 @@ QSet<QTabBar*> QDockAreaLayout::usedTabBars() const } return result; } -#endif // Returns the set of all used separator widgets QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const @@ -3253,6 +3263,7 @@ QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const } return result; } +#endif QRect QDockAreaLayout::gapRect(const QList<int> &path) const { diff --git a/src/gui/widgets/qdockarealayout_p.h b/src/gui/widgets/qdockarealayout_p.h index 99a9dbb..bd2067b 100644 --- a/src/gui/widgets/qdockarealayout_p.h +++ b/src/gui/widgets/qdockarealayout_p.h @@ -196,9 +196,10 @@ public: QRect rect; QMainWindow *mainWindow; QList<QDockAreaLayoutItem> item_list; - +#ifndef QT_NO_TABBAR void updateSeparatorWidgets() const; QSet<QWidget*> usedSeparatorWidgets() const; +#endif //QT_NO_TABBAR #ifndef QT_NO_TABBAR quintptr currentTabId() const; @@ -233,6 +234,7 @@ public: QDockAreaLayout(QMainWindow *win); QDockAreaLayoutInfo docks[4]; int sep; // separator extent + bool fallbackToSizeHints; //determines if we should use the sizehint for the dock areas (true until the layout is restored or the central widget is set) mutable QVector<QWidget*> separatorWidgets; bool isValid() const; @@ -278,7 +280,9 @@ public: const QPoint &mouse) const; QRegion separatorRegion() const; int separatorMove(const QList<int> &separator, const QPoint &origin, const QPoint &dest); +#ifndef QT_NO_TABBAR void updateSeparatorWidgets() const; +#endif //QT_NO_TABBAR QLayoutItem *itemAt(int *x, int index) const; QLayoutItem *takeAt(int *x, int index); @@ -292,9 +296,10 @@ public: QRect gapRect(const QList<int> &path) const; void keepSize(QDockWidget *w); - +#ifndef QT_NO_TABBAR QSet<QTabBar*> usedTabBars() const; QSet<QWidget*> usedSeparatorWidgets() const; +#endif //QT_NO_TABBAR }; QT_END_NAMESPACE diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp index a574262f..a8e2a37 100644 --- a/src/gui/widgets/qdockwidget.cpp +++ b/src/gui/widgets/qdockwidget.cpp @@ -456,7 +456,7 @@ int QDockWidgetLayout::titleHeight() const int mw = q->style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, 0, q); - return qMax(buttonHeight + 2, titleFontMetrics.lineSpacing() + 2*mw); + return qMax(buttonHeight + 2, titleFontMetrics.height() + 2*mw); } void QDockWidgetLayout::setGeometry(const QRect &geometry) @@ -685,8 +685,6 @@ void QDockWidgetPrivate::_q_toggleTopLevel() void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca) { - Q_Q(QDockWidget); - if (state != 0) return; @@ -694,8 +692,6 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca) Q_ASSERT(win != 0); QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout()); Q_ASSERT(layout != 0); - if (layout->layoutState.indexOf(q).isEmpty()) //The dock widget has not been added into the main window - return; if (layout->pluggingWidget != 0) // the main window is animating a docking operation return; @@ -1012,6 +1008,12 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect { Q_Q(QDockWidget); + if (!floating && parent) { + QMainWindowLayout *mwlayout = qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout()); + if (!mwlayout || mwlayout->dockWidgetArea(q) == Qt::NoDockWidgetArea) + return; // this dockwidget can't be redocked + } + bool wasFloating = q->isFloating(); bool hidden = q->isHidden(); diff --git a/src/gui/widgets/qfontcombobox.cpp b/src/gui/widgets/qfontcombobox.cpp index 7b39823..806db59 100644 --- a/src/gui/widgets/qfontcombobox.cpp +++ b/src/gui/widgets/qfontcombobox.cpp @@ -194,7 +194,7 @@ QSize QFontFamilyDelegate::sizeHint(const QStyleOptionViewItem &option, // font.setFamily(text); font.setPointSize(QFontInfo(font).pointSize() * 3/2); QFontMetrics fontMetrics(font); - return QSize(fontMetrics.width(text), fontMetrics.lineSpacing()); + return QSize(fontMetrics.width(text), fontMetrics.height()); } diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 7f9ff82..8f17e98 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -447,8 +447,9 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) cursorPositionChanged = true; } } - +#ifndef QT_NO_IM setPreeditArea(m_cursor, event->preeditString()); +#endif //QT_NO_IM m_preeditCursor = event->preeditString().length(); m_hideCursor = false; QList<QTextLayout::FormatRange> formats; diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 68898b6..f8e1a5d 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -174,8 +174,10 @@ public: void setMaxLength(int maxLength); int maxLength() const; +#ifndef QT_NO_VALIDATOR const QValidator *validator() const; void setValidator(const QValidator *); +#endif #ifndef QT_NO_COMPLETER QCompleter *completer() const; @@ -282,7 +284,9 @@ private: bool finishChange(int validateFromState = -1, bool update = false, bool edited = true); +#ifndef QT_NO_VALIDATOR QPointer<QValidator> m_validator; +#endif QPointer<QCompleter> m_completer; #ifndef QT_NO_COMPLETER bool advanceToEnabledItem(int dir); @@ -623,6 +627,7 @@ inline int QLineControl::maxLength() const return m_maxLength; } +#ifndef QT_NO_VALIDATOR inline const QValidator *QLineControl::validator() const { return m_validator; @@ -632,6 +637,7 @@ inline void QLineControl::setValidator(const QValidator *v) { m_validator = const_cast<QValidator*>(v); } +#endif #ifndef QT_NO_COMPLETER inline QCompleter *QLineControl::completer() const diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp index 629e839..e4252b5 100644 --- a/src/gui/widgets/qlineedit.cpp +++ b/src/gui/widgets/qlineedit.cpp @@ -624,7 +624,7 @@ QSize QLineEdit::sizeHint() const Q_D(const QLineEdit); ensurePolished(); QFontMetrics fm(font()); - int h = qMax(fm.lineSpacing(), 14) + 2*d->verticalMargin + int h = qMax(fm.height(), 14) + 2*d->verticalMargin + d->topTextMargin + d->bottomTextMargin + d->topmargin + d->bottommargin; int w = fm.width(QLatin1Char('x')) * 17 + 2*d->horizontalMargin diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 687e1bc..1b5d1cd 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -180,6 +180,21 @@ int QMenuPrivate::scrollerHeight() const } //Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't +QRect QMenuPrivate::popupGeometry(const QWidget *widget) const +{ +#ifdef Q_WS_WIN + return QApplication::desktop()->screenGeometry(widget); +#elif defined Q_WS_X11 + if (X11->desktopEnvironment == DE_KDE) + return QApplication::desktop()->screenGeometry(widget); + else + return QApplication::desktop()->availableGeometry(widget); +#else + return QApplication::desktop()->availableGeometry(widget); +#endif +} + +//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't QRect QMenuPrivate::popupGeometry(int screen) const { #ifdef Q_WS_WIN @@ -234,7 +249,7 @@ void QMenuPrivate::updateActionRects() const } int max_column_width = 0, - dh = popupGeometry(QApplication::desktop()->screenNumber(q)).height(), + dh = popupGeometry(q).height(), y = 0; QStyle *style = q->style(); QStyleOption opt; @@ -744,7 +759,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc if (newScrollFlags & QMenuScroller::ScrollUp) newOffset -= vmargin; - QRect screen = popupGeometry(QApplication::desktop()->screenNumber(q)); + QRect screen = popupGeometry(q); const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q); if (q->height() < screen.height()-(desktopFrame*2)-1) { QRect geom = q->geometry(); @@ -960,10 +975,19 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) return false; } +class ExceptionGuard +{ +public: + inline ExceptionGuard(bool *w = 0) : watched(w) { Q_ASSERT(!(*watched)); *watched = true; } + inline ~ExceptionGuard() { *watched = false; } + inline operator bool() { return *watched; } +private: + bool *watched; +}; + void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self) { - Q_ASSERT(!activationRecursionGuard); - activationRecursionGuard = true; + ExceptionGuard guard(&activationRecursionGuard); #ifdef QT3_SUPPORT const int actionId = q_func()->findIdForAction(action); #endif @@ -1008,7 +1032,6 @@ void QMenuPrivate::activateCausedStack(const QList<QPointer<QWidget> > &causedSt #endif } } - activationRecursionGuard = false; } void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e, bool self) @@ -1789,7 +1812,15 @@ void QMenu::popup(const QPoint &p, QAction *atAction) d->updateActionRects(); QPoint pos = p; QSize size = sizeHint(); - QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(p)); + QRect screen; +#ifndef QT_NO_GRAPHICSVIEW + bool isEmbedded = d->nearestGraphicsProxyWidget(this); + if (isEmbedded) + screen = d->popupGeometry(this); + else +#endif + screen = d->popupGeometry(QApplication::desktop()->screenNumber(p)); + const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this); bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen); #ifdef QT_KEYPAD_NAVIGATION @@ -1847,6 +1878,10 @@ void QMenu::popup(const QPoint &p, QAction *atAction) if(snapToMouse) //position flowing left from the mouse pos.setX(mouse.x()-size.width()); + //if in a menubar, it should be right-aligned + if (qobject_cast<QMenuBar*>(d->causedPopup.widget)) + pos.rx() -= size.width(); + if (pos.x() < screen.left()+desktopFrame) pos.setX(qMax(p.x(), screen.left()+desktopFrame)); if (pos.x()+size.width()-1 > screen.right()-desktopFrame) @@ -2927,7 +2962,7 @@ void QMenu::internalDelayedPopup() QPoint pos(rightPos); QMenu *caused = qobject_cast<QMenu*>(d->activeMenu->d_func()->causedPopup.widget); - const QRect availGeometry(d->popupGeometry(QApplication::desktop()->screenNumber(caused))); + const QRect availGeometry(d->popupGeometry(caused)); if (isRightToLeft()) { pos = leftPos; if ((caused && caused->x() < x()) || pos.x() < availGeometry.left()) { diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index 9c4f260..9348f7b 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -192,11 +192,12 @@ public: mutable QVector<QRect> actionRects; mutable QWidgetList widgetItems; void updateActionRects() const; - QRect popupGeometry(int screen=-1) const; + QRect popupGeometry(const QWidget *widget) const; + QRect popupGeometry(int screen = -1) const; mutable uint ncols : 4; //4 bits is probably plenty uint collapsibleSeparators : 1; - uint activationRecursionGuard : 1; + bool activationRecursionGuard; //selection static QPointer<QMenu> mouseDown; diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index f2f0722..689d2e1 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -336,30 +336,25 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst) const bool fitUp = (q->mapToGlobal(adjustedActionRect.topLeft()).y() >= popup_size.height()); const bool fitDown = (pos.y() + popup_size.height() <= screenRect.bottom()); + const bool rtl = q->isRightToLeft(); const int actionWidth = adjustedActionRect.width(); if (!fitUp && !fitDown) { //we should shift the menu - bool shouldShiftToRight = !q->isRightToLeft(); - if (q->isRightToLeft() && popup_size.width() > pos.x()) + bool shouldShiftToRight = !rtl; + if (rtl && popup_size.width() > pos.x()) shouldShiftToRight = true; else if (actionWidth + popup_size.width() + pos.x() > screenRect.right()) shouldShiftToRight = false; - if (shouldShiftToRight) - pos.rx() += actionWidth; - else - pos.rx() -= popup_size.width(); - } else if (q->isRightToLeft()) { - pos.setX(pos.x()-(popup_size.width() - actionWidth)); - } - - if(pos.x() < screenRect.x()) { - pos.setX(screenRect.x()); - } else { - const int off = pos.x()+popup_size.width() - screenRect.right(); - if(off > 0) - pos.setX(qMax(screenRect.x(), pos.x()-off)); - + if (shouldShiftToRight) { + pos.rx() += actionWidth + (rtl ? popup_size.width() : 0); + } else { + //shift to left + if (!rtl) + pos.rx() -= popup_size.width(); + } + } else if (rtl) { + pos.rx() += actionWidth; } if(!defaultPopDown || (fitUp && !fitDown)) diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index 22438bf..bb93546 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -357,10 +357,8 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block) Q_D(QPlainTextDocumentLayout); QTextDocument *doc = document(); qreal margin = doc->documentMargin(); - QFontMetrics fm(doc->defaultFont()); qreal blockMaximumWidth = 0; - int leading = qMax(0, fm.leading()); qreal height = 0; QTextLayout *tl = block.layout(); QTextOption option = doc->defaultTextOption(); @@ -381,9 +379,8 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block) QTextLine line = tl->createLine(); if (!line.isValid()) break; + line.setLeadingIncluded(true); line.setLineWidth(availableWidth); - - height += leading; line.setPosition(QPointF(margin, height)); height += line.height(); blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin); @@ -1602,7 +1599,6 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) return; } } -#endif // QT_NO_SHORTCUT if (!(tif & Qt::TextEditable)) { switch (e->key()) { @@ -1630,6 +1626,7 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) } return; } +#endif // QT_NO_SHORTCUT d->sendControlEvent(e); #ifdef QT_KEYPAD_NAVIGATION diff --git a/src/gui/widgets/qpushbutton.cpp b/src/gui/widgets/qpushbutton.cpp index 1352e1b..eb34336 100644 --- a/src/gui/widgets/qpushbutton.cpp +++ b/src/gui/widgets/qpushbutton.cpp @@ -590,7 +590,7 @@ void QPushButtonPrivate::_q_popupPressed() int x = globalPos.x(); int y = globalPos.y(); if (horizontal) { - if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->height()) { + if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->availableGeometry(q).height()) { y += rect.height(); } else { y -= menuSize.height(); @@ -598,7 +598,7 @@ void QPushButtonPrivate::_q_popupPressed() if (q->layoutDirection() == Qt::RightToLeft) x += rect.width() - menuSize.width(); } else { - if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->width()) + if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->availableGeometry(q).width()) x += rect.width(); else x -= menuSize.width(); diff --git a/src/gui/widgets/qsplitter.cpp b/src/gui/widgets/qsplitter.cpp index e3121ae..520a802 100644 --- a/src/gui/widgets/qsplitter.cpp +++ b/src/gui/widgets/qsplitter.cpp @@ -360,13 +360,26 @@ void QSplitterPrivate::recalc(bool update) before a hidden widget must be hidden. */ bool first = true; + bool allInvisible = n != 0; for (int i = 0; i < n ; ++i) { QSplitterLayoutStruct *s = list.at(i); - s->handle->setHidden(first || s->widget->isHidden()); - if (!s->widget->isHidden()) + bool widgetHidden = s->widget->isHidden(); + if (allInvisible && !widgetHidden && !s->collapsed) + allInvisible = false; + s->handle->setHidden(first || widgetHidden); + if (!widgetHidden) first = false; } + if (allInvisible) + for (int i = 0; i < n ; ++i) { + QSplitterLayoutStruct *s = list.at(i); + if (!s->widget->isHidden()) { + s->collapsed = false; + break; + } + } + int fi = 2 * q->frameWidth(); int maxl = fi; int minl = fi; diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index 6c9761c..3935c55 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -1694,6 +1694,9 @@ void QTabBar::mousePressEvent(QMouseEvent *event) d->moveTabFinished(d->pressedIndex); d->pressedIndex = d->indexAtPos(event->pos()); +#ifdef Q_WS_MAC + d->previousPressedIndex = d->pressedIndex; +#endif if (d->validIndex(d->pressedIndex)) { QStyleOptionTabBarBaseV2 optTabBase; optTabBase.init(this); @@ -1774,6 +1777,17 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event) update(); } +#ifdef Q_WS_MAC + } else if (!d->documentMode && event->buttons() == Qt::LeftButton && d->previousPressedIndex != -1) { + int newPressedIndex = d->indexAtPos(event->pos()); + if (d->pressedIndex == -1 && d->previousPressedIndex == newPressedIndex) { + d->pressedIndex = d->previousPressedIndex; + update(tabRect(d->pressedIndex)); + } else if(d->pressedIndex != newPressedIndex) { + d->pressedIndex = -1; + update(tabRect(d->previousPressedIndex)); + } +#endif } if (event->buttons() != Qt::LeftButton) { @@ -1798,6 +1812,7 @@ void QTabBarPrivate::setupMovableTab() QPixmap grabImage(grabRect.size()); grabImage.fill(Qt::transparent); QStylePainter p(&grabImage, q); + p.initFrom(q); QStyleOptionTabV3 tab; q->initStyleOption(&tab, pressedIndex); @@ -1865,7 +1880,9 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event) event->ignore(); return; } - +#ifdef Q_WS_MAC + d->previousPressedIndex = -1; +#endif if (d->movable && d->dragInProgress && d->validIndex(d->pressedIndex)) { int length = d->tabList[d->pressedIndex].dragOffset; int width = verticalTabs(d->shape) diff --git a/src/gui/widgets/qtabbar_p.h b/src/gui/widgets/qtabbar_p.h index 494a340..9f3285b 100644 --- a/src/gui/widgets/qtabbar_p.h +++ b/src/gui/widgets/qtabbar_p.h @@ -77,7 +77,11 @@ public: :currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false), drawBase(true), scrollOffset(0), expanding(true), closeButtonOnTabs(false), selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false), - dragInProgress(false), documentMode(false), movingTab(0) {} + dragInProgress(false), documentMode(false), movingTab(0) +#ifdef Q_WS_MAC + , previousPressedIndex(-1) +#endif + {} int currentIndex; int pressedIndex; @@ -195,7 +199,9 @@ public: bool documentMode; QWidget *movingTab; - +#ifdef Q_WS_MAC + int previousPressedIndex; +#endif // shared by tabwidget and qtabbar static void initStyleBaseOption(QStyleOptionTabBarBaseV2 *optTabBase, QTabBar *tabbar, QSize size) { diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp index 9aeb033..d22bd54 100644 --- a/src/gui/widgets/qtabwidget.cpp +++ b/src/gui/widgets/qtabwidget.cpp @@ -313,7 +313,16 @@ void QTabWidget::initStyleOption(QStyleOptionTabWidgetFrame *option) const : QTabBar::TriangularEast; break; } + option->tabBarSize = t; + + if (QStyleOptionTabWidgetFrameV2 *tabframe = qstyleoption_cast<QStyleOptionTabWidgetFrameV2*>(option)) { + QRect tbRect = tabBar()->geometry(); + QRect selectedTabRect = tabBar()->tabRect(tabBar()->currentIndex()); + tabframe->tabBarRect = tbRect; + selectedTabRect.moveTopLeft(selectedTabRect.topLeft() + tbRect.topLeft()); + tabframe->selectedTabRect = selectedTabRect; + } } /*! @@ -756,7 +765,7 @@ void QTabWidget::setUpLayout(bool onlyCheck) if (onlyCheck && !d->dirty) return; // nothing to do - QStyleOptionTabWidgetFrame option; + QStyleOptionTabWidgetFrameV2 option; initStyleOption(&option); // this must be done immediately, because QWidgetItem relies on it (even if !isVisible()) @@ -1167,8 +1176,8 @@ void QTabWidget::tabRemoved(int index) void QTabWidget::paintEvent(QPaintEvent *) { Q_D(QTabWidget); - QStylePainter p(this); if (documentMode()) { + QStylePainter p(this, tabBar()); if (QWidget *w = cornerWidget(Qt::TopLeftCorner)) { QStyleOptionTabBarBaseV2 opt; QTabBarPrivate::initStyleBaseOption(&opt, tabBar(), w->size()); @@ -1185,8 +1194,9 @@ void QTabWidget::paintEvent(QPaintEvent *) } return; } + QStylePainter p(this); - QStyleOptionTabWidgetFrame opt; + QStyleOptionTabWidgetFrameV2 opt; initStyleOption(&opt); opt.rect = d->panelRect; p.drawPrimitive(QStyle::PE_FrameTabWidget, opt); diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp index b894aa8..d995e0f 100644 --- a/src/gui/widgets/qtextedit.cpp +++ b/src/gui/widgets/qtextedit.cpp @@ -1246,7 +1246,6 @@ void QTextEdit::keyPressEvent(QKeyEvent *e) return; } } -#endif // QT_NO_SHORTCUT if (!(tif & Qt::TextEditable)) { switch (e->key()) { @@ -1274,6 +1273,7 @@ void QTextEdit::keyPressEvent(QKeyEvent *e) } return; } +#endif // QT_NO_SHORTCUT { QTextCursor cursor = d->control->textCursor(); @@ -2079,8 +2079,8 @@ void QTextEdit::setReadOnly(bool ro) } else { flags = Qt::TextEditorInteraction; } - setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); d->control->setTextInteractionFlags(flags); + setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); } /*! diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index 40c0b02..5596ca4 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -183,6 +183,9 @@ void QToolBarPrivate::setWindowState(bool floating, bool unplug, const QRect &re if (visible) q->show(); + + if (floating != wasFloating) + emit q->topLevelChanged(floating); } void QToolBarPrivate::initDrag(const QPoint &pos) @@ -518,6 +521,19 @@ void QToolBarPrivate::plug(const QRect &r) */ /*! + \since 4.6 + + \fn void QToolBar::topLevelChanged(bool topLevel) + + This signal is emitted when the \l floating property changes. + The \a topLevel parameter is true if the toolbar is now floating; + otherwise it is false. + + \sa isWindow() +*/ + + +/*! Constructs a QToolBar with the given \a parent. */ QToolBar::QToolBar(QWidget *parent) diff --git a/src/gui/widgets/qtoolbar.h b/src/gui/widgets/qtoolbar.h index a084673..a1a24f0 100644 --- a/src/gui/widgets/qtoolbar.h +++ b/src/gui/widgets/qtoolbar.h @@ -142,6 +142,7 @@ Q_SIGNALS: void orientationChanged(Qt::Orientation orientation); void iconSizeChanged(const QSize &iconSize); void toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle); + void topLevelChanged(bool topLevel); protected: void actionEvent(QActionEvent *event); diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp index f440961..bdd3c75 100644 --- a/src/gui/widgets/qwidgetanimator.cpp +++ b/src/gui/widgets/qwidgetanimator.cpp @@ -105,7 +105,9 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo #else //we do it in one shot widget->setGeometry(final_geometry); +#ifndef QT_NO_MAINWINDOW m_mainWindowLayout->animationFinished(widget); +#endif //QT_NO_MAINWINDOW #endif //QT_NO_ANIMATION } |