diff options
Diffstat (limited to 'src/gui')
35 files changed, 869 insertions, 339 deletions
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 14f19f2..297c900 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -317,6 +317,7 @@ QFileDialog::QFileDialog(QWidget *parent, Qt::WindowFlags f) { Q_D(QFileDialog); d->init(); + d->lineEdit()->selectAll(); } /*! @@ -334,6 +335,7 @@ QFileDialog::QFileDialog(QWidget *parent, { Q_D(QFileDialog); d->init(directory, filter, caption); + d->lineEdit()->selectAll(); } /*! diff --git a/src/gui/dialogs/qfontdialog.cpp b/src/gui/dialogs/qfontdialog.cpp index ca882c5..60fae27 100644 --- a/src/gui/dialogs/qfontdialog.cpp +++ b/src/gui/dialogs/qfontdialog.cpp @@ -602,6 +602,8 @@ void QFontDialogPrivate::updateStyles() } if (!found) styleList->setCurrentItem(0); + } else { + styleList->setCurrentItem(0); } styleEdit->setText(styleList->currentText()); diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index eee9bbf..e971fd8 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -67,6 +67,7 @@ \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 @@ -795,7 +796,7 @@ QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent) { Q_D(QGraphicsBlurEffect); - d->filter->setBlurHint(QPixmapBlurFilter::PerformanceHint); + d->filter->setBlurHint(Qt::PerformanceHint); } /*! @@ -839,48 +840,34 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) */ /*! - \enum QGraphicsBlurEffect::BlurHint - - \since 4.6 - - This enum describes the hint of a blur graphics effect. - - \value PerformanceHint Using this value hints that performance is the - most important factor, at the potential cost of lower quality. - - \value QualityHint Using this value hints that a higher quality blur is - preferred over a fast blur. -*/ - -/*! \property QGraphicsBlurEffect::blurHint \brief the blur hint of the effect. - Use the PerformanceHint blur hint to say that you want a faster blur, - and the QualityHint blur hint to say that you prefer a higher quality blur. + 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 the PerformanceHint. + When animating the blur radius it's recommended to use Qt::PerformanceHint. - By default, the blur hint is PerformanceHint. + By default, the blur hint is Qt::PerformanceHint. */ -QGraphicsBlurEffect::BlurHint QGraphicsBlurEffect::blurHint() const +Qt::RenderHint QGraphicsBlurEffect::blurHint() const { Q_D(const QGraphicsBlurEffect); - return BlurHint(d->filter->blurHint()); + return d->filter->blurHint(); } -void QGraphicsBlurEffect::setBlurHint(QGraphicsBlurEffect::BlurHint hint) +void QGraphicsBlurEffect::setBlurHint(Qt::RenderHint hint) { Q_D(QGraphicsBlurEffect); - if (BlurHint(d->filter->blurHint()) == hint) + if (d->filter->blurHint() == hint) return; - d->filter->setBlurHint(QPixmapBlurFilter::BlurHint(hint)); + d->filter->setBlurHint(hint); emit blurHintChanged(hint); } /*! - \fn void QGraphicsBlurEffect::blurHintChanged(QGraphicsBlurEffect::BlurHint hint) + \fn void QGraphicsBlurEffect::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. @@ -1305,5 +1292,237 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour 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. + + \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. +*/ + +/*! + \reimp +*/ +void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) +{ + Q_D(QGraphicsBloomEffect); + if (d->strength < 0.001) { + source->draw(painter); + return; + } + + const Qt::CoordinateSystem system = source->isPixmap() + ? Qt::LogicalCoordinates : Qt::DeviceCoordinates; + QPoint offset; + QPixmap pixmap = source->pixmap(system, &offset); + QImage result = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + + // Blur. + QPainter blurPainter(&pixmap); + d->blurFilter.draw(&blurPainter, QPointF(), pixmap); + blurPainter.end(); + + // Brighten. + QImage overlay = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + const int numBits = overlay.width() * overlay.height(); + QRgb *bits = reinterpret_cast<QRgb *>(overlay.bits()); + for (int i = 0; i < numBits; ++i) { + const QRgb bit = bits[i]; + bits[i] = qRgba(d->colorTable[qRed(bit)], d->colorTable[qGreen(bit)], + d->colorTable[qBlue(bit)], qAlpha(bit)); + } + + // Composite. + QPainter compPainter(&result); + compPainter.setCompositionMode(QPainter::CompositionMode_Overlay); + compPainter.setOpacity(d->strength); + compPainter.drawImage(0, 0, overlay); + compPainter.end(); + + if (system == Qt::DeviceCoordinates) { + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawImage(offset, result); + painter->setWorldTransform(restoreTransform); + } else { + painter->drawImage(offset, result); + } +} + QT_END_NAMESPACE diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index c256381..c5d3ede 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -224,27 +224,22 @@ class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) - Q_PROPERTY(BlurHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) + Q_PROPERTY(Qt::RenderHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) public: - enum BlurHint { - PerformanceHint, - QualityHint - }; - QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); QRectF boundingRectFor(const QRectF &rect) const; int blurRadius() const; - BlurHint blurHint() const; + Qt::RenderHint blurHint() const; public Q_SLOTS: void setBlurRadius(int blurRadius); - void setBlurHint(BlurHint blurHint); + void setBlurHint(Qt::RenderHint hint); Q_SIGNALS: void blurRadiusChanged(int blurRadius); - void blurHintChanged(BlurHint blurHint); + void blurHintChanged(Qt::RenderHint hint); protected: void draw(QPainter *painter, QGraphicsEffectSource *source); @@ -339,6 +334,44 @@ 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 e109790..96eda0e 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -185,6 +185,18 @@ public: uint hasOpacityMask : 1; }; +class QGraphicsBloomEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsBlurEffect) +public: + QGraphicsBloomEffectPrivate() : brightness(70), strength(0.7) {} + + QPixmapBlurFilter blurFilter; + int colorTable[256]; + int brightness; + qreal strength; +}; + QT_END_NAMESPACE #endif // QGRAPHICSEFFECT_P_H diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index d7a7bd2..bc9c73f 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -564,6 +564,21 @@ supportsExtension() and setExtension(). */ +/*! + \enum QGraphicsItem::PanelModality + + This enum specifies the behavior of a modal panel. A modal panel + is one that blocks input to other panels. Note that items that + are children of a modal panel are not blocked. + + The values are: + \value NonModal The panel is not modal and does not block input to other panels. + \value PanelModal The panel is modal to a single item hierarchy and blocks input to its parent pane, all grandparent panels, and all siblings of its parent and grandparent panels. + \value SceneModal The window is modal to the entire scene and blocks input to all panels. + + \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel +*/ + #include "qgraphicsitem.h" #ifndef QT_NO_GRAPHICSVIEW @@ -1649,6 +1664,16 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0)); } + if ((d_ptr->panelModality != NonModal) + && d_ptr->scene + && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) { + // update the panel's modal state + if (flags & ItemIsPanel) + d_ptr->scene->d_func()->enterModal(this); + else + d_ptr->scene->d_func()->leaveModal(this); + } + if (d_ptr->scene) { d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, @@ -1725,6 +1750,87 @@ void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize) update(); } +/*! + \since 4.6 + + Returns the modality for this item. +*/ +QGraphicsItem::PanelModality QGraphicsItem::panelModality() const +{ + return d_ptr->panelModality; +} + +/*! + \since 4.6 + + Sets the modality for this item to \a panelModality. + + Changing the modality of a visible item takes effect immediately. +*/ +void QGraphicsItem::setPanelModality(PanelModality panelModality) +{ + if (d_ptr->panelModality == panelModality) + return; + + PanelModality previousModality = d_ptr->panelModality; + bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible()); + if (enterLeaveModal && panelModality == NonModal) + d_ptr->scene->d_func()->leaveModal(this); + d_ptr->panelModality = panelModality; + if (enterLeaveModal && d_ptr->panelModality != NonModal) + d_ptr->scene->d_func()->enterModal(this, previousModality); +} + +/*! + \since 4.6 + + Returns true if this item is blocked by a modal panel, false otherwise. If \a blockingPanel is + non-zero, \a blockingPanel will be set to the modal panel that is blocking this item. If this + item is not blocked, \a blockingPanel will not be set by this function. + + This function always returns false for items not in a scene. + + \sa panelModality() setPanelModality() PanelModality +*/ +bool QGraphicsItem::isBlockedByModalPanel(QGraphicsItem **blockingPanel) const +{ + if (!d_ptr->scene) + return false; + + + QGraphicsItem *dummy = 0; + if (!blockingPanel) + blockingPanel = &dummy; + + QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func(); + if (scene_d->modalPanels.isEmpty()) + return false; + + // ### + if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this) + return false; + + for (int i = 0; i < scene_d->modalPanels.count(); ++i) { + QGraphicsItem *modalPanel = scene_d->modalPanels.at(i); + if (modalPanel->panelModality() == QGraphicsItem::SceneModal) { + // Scene modal panels block all non-descendents. + if (modalPanel != this && !modalPanel->isAncestorOf(this)) { + *blockingPanel = modalPanel; + return true; + } + } else { + // Window modal panels block ancestors and siblings/cousins. + if (modalPanel != this + && !modalPanel->isAncestorOf(this) + && commonAncestorItem(modalPanel)) { + *blockingPanel = modalPanel; + return true; + } + } + } + return false; +} + #ifndef QT_NO_TOOLTIP /*! Returns the item's tool tip, or an empty QString if no tool tip has been @@ -1934,6 +2040,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo q->ungrabMouse(); if (scene->d_func()->keyboardGrabberItems.contains(q)) q->ungrabKeyboard(); + if (q->isPanel() && panelModality != QGraphicsItem::NonModal) + scene->d_func()->leaveModal(q_ptr); } if (q_ptr->hasFocus() && scene) { // Hiding the closest non-panel ancestor of the focus item @@ -1955,10 +2063,15 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } else { geometryChanged = 1; paintedViewBoundingRectsNeedRepaint = 1; - if (isWidget && scene) { - QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); - if (widget->windowType() == Qt::Popup) - scene->d_func()->addPopup(widget); + if (scene) { + if (isWidget) { + QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); + if (widget->windowType() == Qt::Popup) + scene->d_func()->addPopup(widget); + } + if (q->isPanel() && panelModality != QGraphicsItem::NonModal) { + scene->d_func()->enterModal(q_ptr); + } } } @@ -2781,7 +2894,7 @@ bool QGraphicsItem::hasFocus() const the preferred focus item for its subtree of items, should it later become visible. - As a result of calling this function, this item will receive a + As a result of calling this function, this item will receive a \l{focusInEvent()}{focus in event} with \a focusReason. If another item already has focus, that item will first receive a \l{focusOutEvent()} {focus out event} indicating that it has lost input focus. @@ -3299,7 +3412,7 @@ QMatrix QGraphicsItem::matrix() const The transformation matrix is combined with the item's rotation(), scale() and transformations() into a combined transformations for the item. - + The default transformation matrix is an identity matrix. \sa setTransform(), sceneTransform() @@ -3780,7 +3893,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) // Update and set the new transformation. d_ptr->setTransformHelper(newTransform); - + // Send post-notification. itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform)); } @@ -3914,7 +4027,7 @@ void QGraphicsItem::scale(qreal sx, qreal sy) /*! \obsolete - Use + Use \code setTransform(QTransform().shear(sh, sv), true); @@ -3936,7 +4049,7 @@ void QGraphicsItem::shear(qreal sh, qreal sv) Use setPos() or setTransformOriginPoint() instead. For identical behavior, use - + \code setTransform(QTransform::fromTranslate(dx, dy), true); \endcode @@ -4446,7 +4559,7 @@ bool QGraphicsItem::collidesWithItem(const QGraphicsItem *other, Qt::ItemSelecti Note that this function checks whether the item's shape or bounding rectangle (depending on \a mode) is contained within \a path, and not whether \a path is contained within the items shape - or bounding rectangle. + or bounding rectangle. \sa collidesWithItem(), contains(), shape() */ @@ -6595,7 +6708,7 @@ void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event) if (d_ptr->isWidget) { // Qt::Popup closes when you click outside. QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this); - if (w->windowFlags() & Qt::Popup) { + if ((w->windowFlags() & Qt::Popup) == Qt::Popup) { event->accept(); if (!w->rect().contains(event->pos())) w->close(); @@ -7020,7 +7133,7 @@ void QGraphicsItem::prepareGeometryChange() // if someone is connected to the changed signal or the scene has no views. // Note that this has to be done *after* markDirty to ensure that // _q_processDirtyItems is called before _q_emitUpdated. - if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex) + if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex) || scenePrivate->views.isEmpty()) { if (d_ptr->hasTranslateOnlySceneTransform()) { d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(), @@ -10524,7 +10637,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP effectRect.setRight(deviceWidth - 1); if (bottom + 1 > deviceHeight) effectRect.setBottom(deviceHeight -1); - + } if (effectRect.isEmpty()) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 99d2e12..e6e324a 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -146,6 +146,13 @@ public: DeviceCoordinateCache }; + enum PanelModality + { + NonModal, + PanelModal, + SceneModal + }; + QGraphicsItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC // ### obsolete argument @@ -183,6 +190,10 @@ public: CacheMode cacheMode() const; void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize()); + PanelModality panelModality() const; + void setPanelModality(PanelModality panelModality); + bool isBlockedByModalPanel(QGraphicsItem **blockingPanel = 0) const; + #ifndef QT_NO_TOOLTIP QString toolTip() const; void setToolTip(const QString &toolTip); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 3feccdc..51bfea1 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -131,6 +131,7 @@ public: subFocusItem(0), focusScopeItem(0), imHints(Qt::ImhNone), + panelModality(QGraphicsItem::NonModal), acceptedMouseButtons(0x1f), visible(1), explicitlyHidden(0), @@ -448,6 +449,7 @@ public: QGraphicsItem *subFocusItem; QGraphicsItem *focusScopeItem; Qt::InputMethodHints imHints; + QGraphicsItem::PanelModality panelModality; // Packed 32 bits quint32 acceptedMouseButtons : 5; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4b74b67..a1ff6d2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -565,6 +565,9 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) q->removeItem(item->d_ptr->children.at(i)); } + if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) + leaveModal(item); + // Reset the mouse grabber and focus item data. if (mouseGrabberItems.contains(item)) ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor); @@ -1111,6 +1114,9 @@ void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent) } QGraphicsItem *item = mouseGrabberItems.last(); + if (item->isBlockedByModalPanel()) + return; + for (int i = 0x1; i <= 0x10; i <<= 1) { Qt::MouseButton button = Qt::MouseButton(i); mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget()))); @@ -1134,6 +1140,8 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou // Deliver to any existing mouse grabber. if (!mouseGrabberItems.isEmpty()) { + if (mouseGrabberItems.last()->isBlockedByModalPanel()) + return; // The event is ignored by default, but we disregard the event's // accepted state after delivery; the mouse is grabbed, after all. sendMouseEvent(mouseEvent); @@ -1151,12 +1159,22 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou // Update window activation. QGraphicsItem *topItem = cachedItemsUnderMouse.value(0); QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0; + if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) { + // pass activation to the blocking modal window + newActiveWindow = topItem ? topItem->window() : 0; + } + if (newActiveWindow != q->activeWindow()) q->setActiveWindow(newActiveWindow); // Set focus on the topmost enabled item that can take focus. bool setFocus = false; foreach (QGraphicsItem *item, cachedItemsUnderMouse) { + if (item->isBlockedByModalPanel()) { + // Make sure we don't clear focus. + setFocus = true; + break; + } if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) { if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { setFocus = true; @@ -1165,12 +1183,27 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou break; } } + if (item->isPanel()) + break; + } + + // Check for scene modality. + bool sceneModality = false; + for (int i = 0; i < modalPanels.size(); ++i) { + if (modalPanels.at(i)->panelModality() == QGraphicsItem::SceneModal) { + sceneModality = true; + break; + } } // If nobody could take focus, clear it. - if (!stickyFocus && !setFocus) + if (!stickyFocus && !setFocus && !sceneModality) q->setFocusItem(0, Qt::MouseFocusReason); + // Any item will do. + if (sceneModality && cachedItemsUnderMouse.isEmpty()) + cachedItemsUnderMouse << modalPanels.first(); + // Find a mouse grabber by sending mouse press events to all mouse grabber // candidates one at a time, until the event is accepted. It's accepted by // default, so the receiver has to explicitly ignore it for it to pass @@ -1181,6 +1214,10 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou continue; } + // Check if this item is blocked by a modal panel and deliver the mouse event to the + // blocking panel instead of this item if blocked. + (void) item->isBlockedByModalPanel(&item); + grabMouse(item, /* implicit = */ true); mouseEvent->accept(); @@ -1722,10 +1759,10 @@ QRectF QGraphicsScene::itemsBoundingRect() const return boundingRect; } -/*! - Returns a list of all items on the scene, in no particular order. +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items() const + Returns a list of all items on the scene, in no particular order. - \sa addItem(), removeItem() + \sa addItem(), removeItem() */ QList<QGraphicsItem *> QGraphicsScene::items() const { @@ -1733,11 +1770,11 @@ QList<QGraphicsItem *> QGraphicsScene::items() const return d->index->items(Qt::DescendingOrder); } -/*! - Returns an ordered list of all items on the scene. \a order decides the - sorting. +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const + Returns an ordered list of all items on the scene. \a order decides the + sorting. - \sa addItem(), removeItem() + \sa addItem(), removeItem() */ QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const { @@ -1745,18 +1782,18 @@ QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const return d->index->items(order); } -/*! - \obsolete +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const + \obsolete - Returns all visible items at position \a pos in the scene. The items are - listed in descending stacking order (i.e., the first item in the list is the - top-most item, and the last item is the bottom-most item). + Returns all visible items at position \a pos in the scene. The items are + listed in descending stacking order (i.e., the first item in the list is the + top-most item, and the last item is the bottom-most item). - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. + This function is deprecated and returns incorrect results if the scene + contains items that ignore transformations. Use the overload that takes + a QTransform instead. - \sa itemAt() + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const { @@ -1764,21 +1801,21 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const return d->index->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder); } -/*! - \overload - \obsolete +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const + \overload + \obsolete - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a rectangle. + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a rectangle. - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rectangle are returned. + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a rectangle are returned. - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. + This function is deprecated and returns incorrect results if the scene + contains items that ignore transformations. Use the overload that takes + a QTransform instead. - \sa itemAt() + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const { @@ -1786,47 +1823,45 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe return d->index->items(rectangle, mode, Qt::DescendingOrder); } -/*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const - \obsolete - \since 4.3 +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const + \obsolete + \since 4.3 - This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode). + This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode). - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. + This function is deprecated and returns incorrect results if the scene + contains items that ignore transformations. Use the overload that takes + a QTransform instead. */ /*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, - Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - \overload - \since 4.6 + \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \overload + \since 4.6 - Returns all visible items that, depending on \a mode, are either inside or - intersect with the rectangle defined by \a x, \a y, \a w and \a h, in a list - sorted using \a order. + \brief Returns all visible items that, depending on \a mode, are + either inside or intersect with the rectangle defined by \a x, \a y, + \a w and \a h, in a list sorted using \a order. - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. + \a deviceTransform is the transformation that applies to the view, and needs to + be provided if the scene contains items that ignore transformations. */ -/*! - \overload - \obsolete +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const + \overload + \obsolete - Returns all visible items that, depending on \a mode, are either inside or - intersect with the polygon \a polygon. + Returns all visible items that, depending on \a mode, are either inside or + intersect with the polygon \a polygon. - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a polygon are returned. + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a polygon are returned. - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. + This function is deprecated and returns incorrect results if the scene + contains items that ignore transformations. Use the overload that takes + a QTransform instead. - \sa itemAt() + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const { @@ -1834,21 +1869,21 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS return d->index->items(polygon, mode, Qt::DescendingOrder); } -/*! - \overload - \obsolete +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const + \overload + \obsolete - Returns all visible items that, depending on \a path, are either inside or - intersect with the path \a path. + Returns all visible items that, depending on \a path, are either inside or + intersect with the path \a path. - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. - This function is deprecated and returns incorrect results if the scene - contains items that ignore transformations. Use the overload that takes - a QTransform instead. + This function is deprecated and returns incorrect results if the scene + contains items that ignore transformations. Use the overload that takes + a QTransform instead. - \sa itemAt() + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const { @@ -1856,19 +1891,20 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemS return d->index->items(path, mode, Qt::DescendingOrder); } -/*! - \since 4.6 +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - Returns all visible items that, depending on \a mode, are at the specified \a pos - in a list sorted using \a order. + \since 4.6 - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with \a pos are returned. + \brief Returns all visible items that, depending on \a mode, are at + the specified \a pos in a list sorted using \a order. - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with \a pos are returned. - \sa itemAt() + \a deviceTransform is the transformation that applies to the view, and needs to + be provided if the scene contains items that ignore transformations. + + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1877,20 +1913,21 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti return d->index->items(pos, mode, order, deviceTransform); } -/*! - \overload - \since 4.6 +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \overload + \since 4.6 - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a rect and return a list sorted using \a order. + \brief Returns all visible items that, depending on \a mode, are + either inside or intersect with the specified \a rect and return a + list sorted using \a order. - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rect are returned. + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a rect are returned. - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. + \a deviceTransform is the transformation that applies to the view, and needs to + be provided if the scene contains items that ignore transformations. - \sa itemAt() + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1899,20 +1936,21 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti return d->index->items(rect, mode, order, deviceTransform); } -/*! - \overload - \since 4.6 +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \overload + \since 4.6 - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a polygon and return a list sorted using \a order. + \brief Returns all visible items that, depending on \a mode, are + either inside or intersect with the specified \a polygon and return + a list sorted using \a order. - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a polygon are returned. + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a polygon are returned. - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. + \a deviceTransform is the transformation that applies to the view, and needs to + be provided if the scene contains items that ignore transformations. - \sa itemAt() + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1921,20 +1959,21 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS return d->index->items(polygon, mode, order, deviceTransform); } -/*! - \overload - \since 4.6 +/*! \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \overload + \since 4.6 - Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a path and return a list sorted using \a order. + \brief Returns all visible items that, depending on \a mode, are + either inside or intersect with the specified \a path and return a + list sorted using \a order. - The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. - \a deviceTransform is the transformation that applies to the view, and needs to - be provided if the scene contains items that ignore transformations. + \a deviceTransform is the transformation that applies to the view, and needs to + be provided if the scene contains items that ignore transformations. - \sa itemAt() + \sa itemAt() */ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -2403,6 +2442,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) d->selectedItems << item; if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup) d->addPopup(static_cast<QGraphicsWidget *>(item)); + if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) + d->enterModal(item); // Update creation order focus chain. Make sure to leave the widget's // internal tab order intact. @@ -3205,8 +3246,12 @@ bool QGraphicsScene::event(QEvent *event) } return false; case QEvent::GraphicsSceneMouseMove: - mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); + { + QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event); + d->lastSceneMousePos = mouseEvent->scenePos(); + mouseMoveEvent(mouseEvent); break; + } case QEvent::GraphicsSceneMousePress: mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event)); break; @@ -3228,8 +3273,12 @@ bool QGraphicsScene::event(QEvent *event) case QEvent::GraphicsSceneHoverEnter: case QEvent::GraphicsSceneHoverLeave: case QEvent::GraphicsSceneHoverMove: - d->dispatchHoverEvent(static_cast<QGraphicsSceneHoverEvent *>(event)); + { + QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event); + d->lastSceneMousePos = hoverEvent->scenePos(); + d->dispatchHoverEvent(hoverEvent); break; + } case QEvent::Leave: d->leaveScene(); break; @@ -3599,8 +3648,10 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent) bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const { - return item->acceptHoverEvents() - || (item->isWidget() && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()); + return (!item->isBlockedByModalPanel() && + (item->acceptHoverEvents() + || (item->isWidget() + && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))); } /*! @@ -3674,7 +3725,9 @@ bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEv } // Generate a move event for the item itself - if (item && !hoverItems.isEmpty() && item == hoverItems.last()) { + if (item + && !hoverItems.isEmpty() + && item == hoverItems.last()) { sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent); return true; } @@ -3708,8 +3761,7 @@ void QGraphicsScenePrivate::leaveScene() while (!hoverItems.isEmpty()) { QGraphicsItem *lastItem = hoverItems.takeLast(); - if (lastItem->acceptHoverEvents() - || (lastItem->isWidget() && static_cast<QGraphicsWidget*>(lastItem)->d_func()->hasDecoration())) + if (itemAcceptsHoverEvents_helper(lastItem)) sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent); } } @@ -3736,6 +3788,8 @@ void QGraphicsScene::keyPressEvent(QKeyEvent *keyEvent) keyEvent->accept(); // Send it; QGraphicsItem::keyPressEvent ignores it. If the event // is filtered out, stop propagating it. + if (p->isBlockedByModalPanel()) + break; if (!d->sendEvent(p, keyEvent)) break; } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem())); @@ -3766,6 +3820,8 @@ void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent) keyEvent->accept(); // Send it; QGraphicsItem::keyPressEvent ignores it. If the event // is filtered out, stop propagating it. + if (p->isBlockedByModalPanel()) + break; if (!d->sendEvent(p, keyEvent)) break; } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem())); @@ -5420,6 +5476,8 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent) for (; it != end; ++it) { QGraphicsItem *item = it.key(); + (void) item->isBlockedByModalPanel(&item); + // determine event type from the state mask QEvent::Type eventType; switch (it.value().first) { @@ -5493,6 +5551,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve break; } } + if (item->isPanel()) + break; } // If nobody could take focus, clear it. @@ -5518,6 +5578,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } break; } + if (item->isPanel()) + break; } touchEvent->setAccepted(eventAccepted); @@ -5536,6 +5598,94 @@ void QGraphicsScenePrivate::updateInputMethodSensitivityInViews() views.at(i)->d_func()->updateInputMethodSensitivity(); } +void QGraphicsScenePrivate::enterModal(QGraphicsItem *panel, QGraphicsItem::PanelModality previousModality) +{ + Q_Q(QGraphicsScene); + Q_ASSERT(panel && panel->isPanel()); + + QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality; + if (previousModality != QGraphicsItem::NonModal) { + // the panel is changing from one modality type to another... temporarily set it back so + // that blockedPanels is populated correctly + panel->d_ptr->panelModality = previousModality; + } + + QSet<QGraphicsItem *> blockedPanels; + QList<QGraphicsItem *> items = q->items(); // ### store panels separately + for (int i = 0; i < items.count(); ++i) { + QGraphicsItem *item = items.at(i); + if (item->isPanel() && item->isBlockedByModalPanel()) + blockedPanels.insert(item); + } + // blockedPanels contains all currently blocked panels + + if (previousModality != QGraphicsItem::NonModal) { + // reset the modality to the proper value, since we changed it above + panel->d_ptr->panelModality = panelModality; + // remove this panel so that it will be reinserted at the front of the stack + modalPanels.removeAll(panel); + } + + modalPanels.prepend(panel); + + if (!hoverItems.isEmpty()) { + // send GraphicsSceneHoverLeave events to newly blocked hoverItems + QGraphicsSceneHoverEvent hoverEvent; + hoverEvent.setScenePos(lastSceneMousePos); + dispatchHoverEvent(&hoverEvent); + } + + if (!mouseGrabberItems.isEmpty() && lastMouseGrabberItemHasImplicitMouseGrab) { + QGraphicsItem *item = mouseGrabberItems.last(); + if (item->isBlockedByModalPanel()) + ungrabMouse(item, /*itemIsDying =*/ false); + } + + QEvent windowBlockedEvent(QEvent::WindowBlocked); + QEvent windowUnblockedEvent(QEvent::WindowUnblocked); + for (int i = 0; i < items.count(); ++i) { + QGraphicsItem *item = items.at(i); + if (item->isPanel()) { + if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) { + // send QEvent::WindowBlocked to newly blocked panels + sendEvent(item, &windowBlockedEvent); + } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) { + // send QEvent::WindowUnblocked to unblocked panels when downgrading + // a panel from SceneModal to PanelModal + sendEvent(item, &windowUnblockedEvent); + } + } + } +} + +void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel) +{ + Q_Q(QGraphicsScene); + Q_ASSERT(panel && panel->isPanel()); + + QSet<QGraphicsItem *> blockedPanels; + QList<QGraphicsItem *> items = q->items(); // ### same as above + for (int i = 0; i < items.count(); ++i) { + QGraphicsItem *item = items.at(i); + if (item->isPanel() && item->isBlockedByModalPanel()) + blockedPanels.insert(item); + } + + modalPanels.removeAll(panel); + + QEvent e(QEvent::WindowUnblocked); + for (int i = 0; i < items.count(); ++i) { + QGraphicsItem *item = items.at(i); + if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel()) + sendEvent(item, &e); + } + + // send GraphicsSceneHoverEnter events to newly unblocked items + QGraphicsSceneHoverEvent hoverEvent; + hoverEvent.setScenePos(lastSceneMousePos); + dispatchHoverEvent(&hoverEvent); +} + QT_END_NAMESPACE #include "moc_qgraphicsscene.cpp" diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 46917ce..5000860 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -160,6 +160,7 @@ public: Qt::DropAction lastDropAction; QList<QGraphicsItem *> cachedItemsUnderMouse; QList<QGraphicsItem *> hoverItems; + QPointF lastSceneMousePos; bool allItemsIgnoreHoverEvents; bool allItemsUseDefaultCursor; void enableMouseTrackingOnViews(); @@ -282,6 +283,11 @@ public: void enableTouchEventsOnViews(); void updateInputMethodSensitivityInViews(); + + QList<QGraphicsItem *> modalPanels; + void enterModal(QGraphicsItem *item, + QGraphicsItem::PanelModality panelModality = QGraphicsItem::NonModal); + void leaveModal(QGraphicsItem *item); }; // QRectF::intersects() returns false always if either the source or target diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h index ed8678d..e34e690 100644 --- a/src/gui/image/qpixmap_x11_p.h +++ b/src/gui/image/qpixmap_x11_p.h @@ -100,6 +100,8 @@ private: friend class QX11WindowSurface; friend class QRasterWindowSurface; friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags + friend class QEglContext; // Needs gl_surface + friend bool qt_createEGLSurfaceForPixmap(QPixmapData*, bool); // Needs gl_surface void release(); diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 3e85236..c26fba3 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -134,6 +134,7 @@ private: friend class QS60PixmapData; 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 ba9a1e2..749b8f3 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(QPixmapBlurFilter::PerformanceHint) {} + QPixmapBlurFilterPrivate() : radius(5), hint(Qt::PerformanceHint) {} int radius; - QPixmapBlurFilter::BlurHint hint; + Qt::RenderHint hint; }; @@ -561,7 +561,7 @@ int QPixmapBlurFilter::radius() const \internal */ -void QPixmapBlurFilter::setBlurHint(QPixmapBlurFilter::BlurHint hint) +void QPixmapBlurFilter::setBlurHint(Qt::RenderHint hint) { Q_D(QPixmapBlurFilter); d->hint = hint; @@ -572,7 +572,7 @@ void QPixmapBlurFilter::setBlurHint(QPixmapBlurFilter::BlurHint hint) \internal */ -QPixmapBlurFilter::BlurHint QPixmapBlurFilter::blurHint() const +Qt::RenderHint QPixmapBlurFilter::blurHint() const { Q_D(const QPixmapBlurFilter); return d->hint; diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 92c8e56..8a2207a 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -126,19 +126,14 @@ class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter Q_DECLARE_PRIVATE(QPixmapBlurFilter) public: - enum BlurHint { - PerformanceHint, - QualityHint - }; - QPixmapBlurFilter(QObject *parent = 0); ~QPixmapBlurFilter(); void setRadius(int radius); - void setBlurHint(BlurHint hint); + void setBlurHint(Qt::RenderHint hint); int radius() const; - BlurHint blurHint() const; + Qt::RenderHint blurHint() const; QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index fc55a0f..c4d17ff 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -222,7 +222,7 @@ void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) TCoeInputCapabilities QCoeFepInputContext::inputCapabilities() { - if (m_inDestruction) { + if (m_inDestruction || !focusWidget()) { return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0); } @@ -554,8 +554,10 @@ void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCur void QCoeFepInputContext::GetCursorSelectionForFep(TCursorSelection& aCursorSelection) const { QWidget *w = focusWidget(); - if (!w) + if (!w) { + aCursorSelection.SetSelection(0,0); return; + } int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt() + m_preeditString.size(); int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt() + m_preeditString.size(); @@ -567,8 +569,10 @@ void QCoeFepInputContext::GetEditorContentForFep(TDes& aEditorContent, TInt aDoc TInt aLengthToRetrieve) const { QWidget *w = focusWidget(); - if (!w) + if (!w) { + aEditorContent.FillZ(aLengthToRetrieve); return; + } QString text = w->inputMethodQuery(Qt::ImSurroundingText).value<QString>(); // FEP expects the preedit string to be part of the editor content, so let's mix it in. @@ -580,8 +584,10 @@ void QCoeFepInputContext::GetEditorContentForFep(TDes& aEditorContent, TInt aDoc void QCoeFepInputContext::GetFormatForFep(TCharFormat& aFormat, TInt /* aDocumentPosition */) const { QWidget *w = focusWidget(); - if (!w) + if (!w) { + aFormat = TCharFormat(); return; + } QFont font = w->inputMethodQuery(Qt::ImFont).value<QFont>(); QFontMetrics metrics(font); @@ -595,8 +601,12 @@ void QCoeFepInputContext::GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLin TInt& aAscent, TInt /* aDocumentPosition */) const { QWidget *w = focusWidget(); - if (!w) + if (!w) { + aLeftSideOfBaseLine = TPoint(0,0); + aHeight = 0; + aAscent = 0; return; + } QRect rect = w->inputMethodQuery(Qt::ImMicroFocus).value<QRect>(); aLeftSideOfBaseLine.iX = rect.left(); diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 303f45b..0fae959 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -3626,12 +3626,13 @@ QItemSelectionModel::SelectionFlags QAbstractItemViewPrivate::extendedSelectionC case Qt::Key_PageUp: case Qt::Key_PageDown: case Qt::Key_Tab: + if (modifiers & Qt::ControlModifier #ifdef QT_KEYPAD_NAVIGATION - return QItemSelectionModel::NoUpdate; -#else - if (modifiers & Qt::ControlModifier) - return QItemSelectionModel::NoUpdate; + // Preserve historical tab order navigation behavior + || QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder #endif + ) + return QItemSelectionModel::NoUpdate; break; case Qt::Key_Select: return QItemSelectionModel::Toggle|selectionBehaviorFlags(); diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 992e754..27c7c94 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -91,6 +91,8 @@ extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp QWidget *qt_button_down = 0; // widget got last button-down +QSymbianControl *QSymbianControl::lastFocusedControl = 0; + QS60Data* qGlobalS60Data() { return qt_s60Data(); @@ -350,6 +352,7 @@ QSymbianControl::~QSymbianControl() { if (S60->curWin == this) S60->curWin = 0; + setFocusSafely(false); S60->appUi()->RemoveFromStack(this); delete m_longTapDetector; } @@ -860,8 +863,23 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) || (qwidget->windowType() & Qt::Popup) == Qt::Popup) return; - QEvent *deferredFocusEvent = new QEvent(QEvent::SymbianDeferredFocusChanged); - QApplication::postEvent(qwidget, deferredFocusEvent); + if (IsFocused() && IsVisible()) { + QApplication::setActiveWindow(qwidget->window()); +#ifdef Q_WS_S60 + // If widget is fullscreen, hide status pane and button container + // otherwise show them. + CEikStatusPane* statusPane = S60->statusPane(); + CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); + bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen; + if (statusPane && (statusPane->IsVisible() == isFullscreen)) + statusPane->MakeVisible(!isFullscreen); + if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen)) + buttonGroup->MakeVisible(!isFullscreen); +#endif + } else if (QApplication::activeWindow() == qwidget->window()) { + QApplication::setActiveWindow(0); + } + // else { We don't touch the active window unless we were explicitly activated or deactivated } } void QSymbianControl::HandleResourceChange(int resourceType) @@ -905,6 +923,31 @@ TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) return CCoeControl::MopSupplyObject(id); } +void QSymbianControl::setFocusSafely(bool focus) +{ + // The stack hack in here is very unfortunate, but it is the only way to ensure proper + // focus in Symbian. If this is not executed, the control which happens to be on + // the top of the stack may randomly be assigned focus by Symbian, for example + // when creating new windows (specifically in CCoeAppUi::HandleStackChanged()). + if (focus) { + S60->appUi()->RemoveFromStack(this); + // Symbian doesn't automatically remove focus from the last focused control, so we need to + // remember it and clear focus ourselves. + if (lastFocusedControl && lastFocusedControl != this) + lastFocusedControl->SetFocus(false); + QT_TRAP_THROWING(S60->appUi()->AddToStackL(this, + ECoeStackPriorityDefault + 1, ECoeStackFlagStandard)); // Note the + 1 + lastFocusedControl = this; + this->SetFocus(true); + } else { + S60->appUi()->RemoveFromStack(this); + QT_TRAP_THROWING(S60->appUi()->AddToStackL(this, + ECoeStackPriorityDefault, ECoeStackFlagStandard)); + lastFocusedControl = 0; + this->SetFocus(false); + } +} + /*! \typedef QApplication::QS60MainApplicationFactory diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 6ecd535..eb9e276 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -1752,79 +1752,18 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam case APPCOMMAND_BASS_UP: key = Qt::Key_BassUp; break; - case APPCOMMAND_BROWSER_BACKWARD: - key = Qt::Key_Back; - break; - case APPCOMMAND_BROWSER_FAVORITES: - key = Qt::Key_Favorites; - break; - case APPCOMMAND_BROWSER_FORWARD: - key = Qt::Key_Forward; - break; - case APPCOMMAND_BROWSER_HOME: - key = Qt::Key_HomePage; - break; - case APPCOMMAND_BROWSER_REFRESH: - key = Qt::Key_Refresh; - break; - case APPCOMMAND_BROWSER_SEARCH: - key = Qt::Key_Search; - break; - case APPCOMMAND_BROWSER_STOP: - key = Qt::Key_Stop; - break; - case APPCOMMAND_LAUNCH_APP1: - key = Qt::Key_Launch0; - break; - case APPCOMMAND_LAUNCH_APP2: - key = Qt::Key_Launch1; - break; - case APPCOMMAND_LAUNCH_MAIL: - key = Qt::Key_LaunchMail; - break; - case APPCOMMAND_LAUNCH_MEDIA_SELECT: - key = Qt::Key_LaunchMedia; - break; - case APPCOMMAND_MEDIA_NEXTTRACK: - key = Qt::Key_MediaNext; - break; - case APPCOMMAND_MEDIA_PLAY_PAUSE: - key = Qt::Key_MediaPlay; - break; - case APPCOMMAND_MEDIA_PREVIOUSTRACK: - key = Qt::Key_MediaPrevious; - break; - case APPCOMMAND_MEDIA_STOP: - key = Qt::Key_MediaStop; - break; case APPCOMMAND_TREBLE_DOWN: key = Qt::Key_TrebleDown; break; case APPCOMMAND_TREBLE_UP: key = Qt::Key_TrebleUp; break; - case APPCOMMAND_VOLUME_DOWN: - key = Qt::Key_VolumeDown; - break; - case APPCOMMAND_VOLUME_MUTE: - key = Qt::Key_VolumeMute; - break; - case APPCOMMAND_VOLUME_UP: - key = Qt::Key_VolumeUp; - break; - // Commands new in Windows XP case APPCOMMAND_HELP: key = Qt::Key_Help; break; case APPCOMMAND_FIND: key = Qt::Key_Search; break; - case APPCOMMAND_PRINT: - key = Qt::Key_Print; - break; - case APPCOMMAND_MEDIA_PLAY: - key = Qt::Key_MediaPlay; - break; default: break; } diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp index 33da0f3..da150fb 100644 --- a/src/gui/kernel/qdnd_x11.cpp +++ b/src/gui/kernel/qdnd_x11.cpp @@ -506,6 +506,7 @@ bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data *atomFormat = textprop.encoding; *dataFormat = textprop.format; *data = QByteArray((const char *) textprop.value, textprop.nitems * textprop.format / 8); + ret = true; DEBUG(" textprop type %lx\n" " textprop name '%s'\n" @@ -541,12 +542,13 @@ bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data dm->xdndMimeTransferedPixmap[dm->xdndMimeTransferedPixmapIndex] = pm; dm->xdndMimeTransferedPixmapIndex = (dm->xdndMimeTransferedPixmapIndex + 1) % 2; + ret = true; } } else { DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", qPrintable(atomName)); } } - return data; + return ret && data != 0; } //$$$ diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index aec757f..b44ef7f 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -571,7 +571,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::Close, 0, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::Close, 1, Qt::CTRL | Qt::Key_W, QApplicationPrivate::KB_Mac}, {QKeySequence::Cut, 1, Qt::CTRL | Qt::Key_X, QApplicationPrivate::KB_All}, - {QKeySequence::Redo, 1, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Win}, + {QKeySequence::Redo, 1, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_S60}, {QKeySequence::Redo, 0, Qt::CTRL | Qt::Key_Y, QApplicationPrivate::KB_Mac},//different priority from above {QKeySequence::Undo, 1, Qt::CTRL | Qt::Key_Z, QApplicationPrivate::KB_All}, {QKeySequence::Back, 1, Qt::CTRL | Qt::Key_BracketLeft, QApplicationPrivate::KB_Mac}, @@ -600,7 +600,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::FindPrevious, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_G, QApplicationPrivate::KB_Win}, {QKeySequence::AddTab, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_N, QApplicationPrivate::KB_KDE}, {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac}, - {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, + {QKeySequence::Redo, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 45695d9..265f971 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -121,6 +121,7 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act softKeyRole = QAction::PositiveSoftKey; break; case CancelSoftKey: + default: softKeyRole = QAction::NegativeSoftKey; break; } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index d1ec74d..d33791b 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -157,6 +157,8 @@ public: void setIgnoreFocusChanged(bool enabled) { m_ignoreFocusChanged = enabled; } void CancelLongTapTimer(); + void setFocusSafely(bool focus); + protected: void Draw(const TRect& aRect) const; void SizeChanged(); @@ -174,6 +176,9 @@ private: #endif private: + static QSymbianControl *lastFocusedControl; + +private: QWidget *qwidget; bool m_ignoreFocusChanged; QLongTapTimer* m_longTapDetector; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 08fe5b9..83593ab 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -8336,12 +8336,6 @@ bool QWidget::event(QEvent *event) (void) QApplication::sendEvent(this, &mouseEvent); break; } - case QEvent::SymbianDeferredFocusChanged: { -#ifdef Q_OS_SYMBIAN - d->handleSymbianDeferredFocusChanged(); -#endif - break; - } #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName(); @@ -11454,6 +11448,10 @@ QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction) QWidget *targetWidget = 0; int shortestDistance = INT_MAX; foreach(QWidget *targetCandidate, QApplication::allWidgets()) { + + if (targetCandidate->focusProxy()) //skip if focus proxy set + continue; + const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint())); if ( targetCandidate != sourceWidget && targetCandidate->focusPolicy() & Qt::TabFocus diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 2a81689..6c879be 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -293,7 +293,6 @@ public: void setMask_sys(const QRegion &); #ifdef Q_OS_SYMBIAN - void handleSymbianDeferredFocusChanged(); void setSoftKeys_sys(const QList<QAction*> &softkeys); #endif diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index d6e0a97..05db8ca 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -367,7 +367,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de } else { stackingFlags = ECoeStackFlagStandard; } + control->MakeVisible(false); QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags)); + // Avoid keyboard focus to a hidden window. + control->setFocusSafely(false); RDrawableWindow *const drawableWindow = control->DrawableWindow(); // Request mouse move events. @@ -399,7 +402,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de } else { stackingFlags = ECoeStackFlagStandard; } + control->MakeVisible(false); QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags)); + // Avoid keyboard focus to a hidden window. + control->setFocusSafely(false); q->setAttribute(Qt::WA_WState_Created); int x, y, w, h; @@ -435,15 +441,15 @@ void QWidgetPrivate::show_sys() if (q->internalWinId()) { - WId id = q->internalWinId(); + QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId()); if (!extra->activated) { QT_TRAP_THROWING(id->ActivateL()); extra->activated = 1; } id->MakeVisible(true); - + if(q->isWindow()) - id->SetFocus(true); + id->setFocusSafely(true); // Force setting of the icon after window is made visible, // this is needed even WA_SetWindowIcon is not set, as in that case we need @@ -461,11 +467,11 @@ void QWidgetPrivate::hide_sys() Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); deactivateWidgetCleanup(); - WId id = q->internalWinId(); + QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId()); if (id) { if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->SetFocus(false); + id->setFocusSafely(false); id->MakeVisible(false); if (QWidgetBackingStore *bs = maybeBackingStore()) bs->releaseBuffer(); @@ -481,36 +487,7 @@ void QWidgetPrivate::setFocus_sys() Q_Q(QWidget); if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup) if (!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged() - q->effectiveWinId()->SetFocus(true); -} - -void QWidgetPrivate::handleSymbianDeferredFocusChanged() -{ - Q_Q(QWidget); - WId control = q->internalWinId(); - - if (!control) { - // This could happen if the widget was reparented, while the focuschange - // was in the event queue. - return; - } - - if (control->IsFocused()) { - QApplication::setActiveWindow(q); -#ifdef Q_WS_S60 - // If widget is fullscreen, hide status pane and button container - // otherwise show them. - CEikStatusPane* statusPane = S60->statusPane(); - CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer(); - bool isFullscreen = q->windowState() & Qt::WindowFullScreen; - if (statusPane && (statusPane->IsVisible() == isFullscreen)) - statusPane->MakeVisible(!isFullscreen); - if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen)) - buttonGroup->MakeVisible(!isFullscreen); -#endif - } else { - QApplication::setActiveWindow(0); - } + static_cast<QSymbianControl *>(q->effectiveWinId())->setFocusSafely(true); } void QWidgetPrivate::raise_sys() @@ -597,7 +574,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) if (q->testAttribute(Qt::WA_DropSiteRegistered)) q->setAttribute(Qt::WA_DropSiteRegistered, false); - WId old_winid = wasCreated ? data.winid : 0; + QSymbianControl *old_winid = static_cast<QSymbianControl *>(wasCreated ? data.winid : 0); if ((q->windowType() == Qt::Desktop)) old_winid = 0; setWinId(0); @@ -607,7 +584,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) if (wasCreated && old_winid) { old_winid->MakeVisible(false); if (old_winid->IsFocused()) // Avoid unnecessary calls to FocusChanged() - old_winid->SetFocus(false); + old_winid->setFocusSafely(false); old_winid->SetParent(0); } @@ -1124,17 +1101,17 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { if (newstate & Qt::WindowMinimized) { if (isVisible()) { - WId id = effectiveWinId(); + QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId()); if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->SetFocus(false); + id->setFocusSafely(false); id->MakeVisible(false); } } else { if (isVisible()) { - WId id = effectiveWinId(); + QSymbianControl *id = static_cast<QSymbianControl *>(effectiveWinId()); id->MakeVisible(true); if (!id->IsFocused()) // Avoid unnecessary calls to FocusChanged() - id->SetFocus(true); + id->setFocusSafely(true); } const QRect normalGeometry = geometry(); const QRect r = top->normalGeometry; @@ -1161,7 +1138,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (!isWindow() && parentWidget()) parentWidget()->d_func()->invalidateBuffer(geometry()); d->deactivateWidgetCleanup(); - WId id = internalWinId(); + QSymbianControl *id = static_cast<QSymbianControl *>(internalWinId()); if (testAttribute(Qt::WA_WState_Created)) { #ifndef QT_NO_IM @@ -1189,7 +1166,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) } if (destroyWindow && !(windowType() == Qt::Desktop) && id) { if (id->IsFocused()) // Avoid unnecessry calls to FocusChanged() - id->SetFocus(false); + id->setFocusSafely(false); id->ControlEnv()->AppUi()->RemoveFromStack(id); // Hack to activate window under destroyed one. With this activation @@ -1299,8 +1276,8 @@ void QWidget::activateWindow() QWidget *tlw = window(); if (tlw->isVisible()) { window()->createWinId(); - WId id = tlw->internalWinId(); - id->SetFocus(true); + QSymbianControl *id = static_cast<QSymbianControl *>(tlw->internalWinId()); + id->setFocusSafely(true); } } diff --git a/src/gui/s60framework/qs60mainapplication.h b/src/gui/s60framework/qs60mainapplication.h index 457764c..5f621e0 100644 --- a/src/gui/s60framework/qs60mainapplication.h +++ b/src/gui/s60framework/qs60mainapplication.h @@ -42,7 +42,7 @@ #ifndef QS60MAINAPPLICATION_H #define QS60MAINAPPLICATION_H -#include <qglobal.h> +#include <QtCore/qglobal.h> #ifdef Q_WS_S60 diff --git a/src/gui/s60framework/qs60mainappui.h b/src/gui/s60framework/qs60mainappui.h index c2c6ef2..321d8d6 100644 --- a/src/gui/s60framework/qs60mainappui.h +++ b/src/gui/s60framework/qs60mainappui.h @@ -42,7 +42,7 @@ #ifndef QS60MAINAPPUI_H #define QS60MAINAPPUI_H -#include <qglobal.h> +#include <QtCore/qglobal.h> #ifdef Q_WS_S60 diff --git a/src/gui/s60framework/qs60maindocument.h b/src/gui/s60framework/qs60maindocument.h index 366d311..1327349 100644 --- a/src/gui/s60framework/qs60maindocument.h +++ b/src/gui/s60framework/qs60maindocument.h @@ -42,7 +42,7 @@ #ifndef QS60MAINDOCUMENT_H #define QS60MAINDOCUMENT_H -#include <qglobal.h> +#include <QtCore/qglobal.h> #ifdef Q_WS_S60 diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 1e57167..6bdb79e 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -2397,8 +2397,6 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple // lets use spinbox frame here as well, as no combobox specific value available. const int frameThickness = cmb->frame ? pixelMetric(PM_SpinBoxFrameWidth, cmb, widget) : 0; const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize); - const int xposMod = (cmb->rect.x()) + width - buttonMargin - buttonWidth; - const int ypos = cmb->rect.y(); QSize buttonSize; buttonSize.setHeight(qMax(8, (cmb->rect.height()>>1) - frameThickness)); //minimum of 8 pixels @@ -2406,15 +2404,18 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple buttonSize = buttonSize.expandedTo(QApplication::globalStrut()); switch (scontrol) { case SC_ComboBoxArrow: - ret.setRect(xposMod, ypos + buttonMargin, buttonWidth, height - 2*buttonMargin); + ret.setRect( + ret.x() + ret.width() - buttonMargin - buttonWidth, + ret.y() + buttonMargin, + buttonWidth, + height - 2*buttonMargin); break; case SC_ComboBoxEditField: { - const int withFrameX = cmb->rect.x() + cmb->rect.width() - frameThickness - buttonSize.width(); - ret = QRect( - frameThickness, - frameThickness, - withFrameX - frameThickness, - cmb->rect.height() - 2*frameThickness); + ret.setRect( + ret.x() + frameThickness, + ret.y() + frameThickness, + ret.width() - 2*frameThickness - buttonSize.width(), + ret.height() - 2*frameThickness); } break; default: diff --git a/src/gui/styles/qs60style.h b/src/gui/styles/qs60style.h index fd18bc3..6be3197 100644 --- a/src/gui/styles/qs60style.h +++ b/src/gui/styles/qs60style.h @@ -76,6 +76,9 @@ public: void unpolish(QWidget *widget); void polish(QApplication *application); void unpolish(QApplication *application); +#ifndef Q_NO_USING_KEYWORD + using QCommonStyle::polish; +#endif void setStyleProperty(const char *name, const QVariant &value); QVariant styleProperty(const char *name) const; diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index b062a3f..6cb8b40 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -731,14 +731,11 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt { const QStyleOptionViewItemV4 *vopt; const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); - bool newStyle = false; + bool newStyle = true; + + if (qobject_cast<const QTableView*>(widget)) + newStyle = false; - if (const QListView *listview = qobject_cast<const QListView *>(widget)) { - if (listview->viewMode() == QListView::IconMode) - newStyle = true; - } else if (qobject_cast<const QTreeView *>(widget)) { - newStyle = true; - } if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) { bool selected = vopt->state & QStyle::State_Selected; bool hover = vopt->state & QStyle::State_MouseOver; @@ -1496,14 +1493,11 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption { const QStyleOptionViewItemV4 *vopt; const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget); - bool newStyle = false; + bool newStyle = true; + + if (qobject_cast<const QTableView*>(widget)) + newStyle = false; - if (const QListView *listview = qobject_cast<const QListView *>(widget)) { - if (listview->viewMode() == QListView::IconMode) - newStyle = true; - } else if (qobject_cast<const QTreeView *>(widget)) { - newStyle = true; - } if (newStyle && view && (vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option))) { /* // We cannot currently get the correct selection color for "explorer style" views diff --git a/src/gui/styles/qwindowsvistastyle_p.h b/src/gui/styles/qwindowsvistastyle_p.h index d4170aa..e9bbb77 100644 --- a/src/gui/styles/qwindowsvistastyle_p.h +++ b/src/gui/styles/qwindowsvistastyle_p.h @@ -84,6 +84,7 @@ #include <qinputdialog.h> #include <qtreeview.h> #include <qlistview.h> +#include <qtableview.h> #include <qbasictimer.h> #include <qcommandlinkbutton.h> diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index ef91983..d73e1c4 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -309,6 +309,7 @@ private: friend class QPicturePaintEngine; friend class QPainterReplayer; friend class QPaintBufferEngine; + friend class QCommandLinkButtonPrivate; #ifndef QT_NO_DATASTREAM friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QFont &); diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 61532b9..95ff4c1 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -403,8 +403,8 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView layout->setMargin(0); #ifdef QT_SOFTKEYS_ENABLED - selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, itemView); - cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, itemView); + selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, this); + cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, this); addAction(selectAction); addAction(cancelAction); #endif @@ -534,6 +534,7 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) this, SLOT(setCurrentIndex(QModelIndex))); disconnect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); + delete view; view = 0; } @@ -571,11 +572,6 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) this, SLOT(setCurrentIndex(QModelIndex))); connect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); - -#ifdef QT_SOFTKEYS_ENABLED - selectAction->setParent(itemView); - cancelAction->setParent(itemView); -#endif } /*! diff --git a/src/gui/widgets/qcommandlinkbutton.cpp b/src/gui/widgets/qcommandlinkbutton.cpp index e64f687..9adf280 100644 --- a/src/gui/widgets/qcommandlinkbutton.cpp +++ b/src/gui/widgets/qcommandlinkbutton.cpp @@ -140,23 +140,34 @@ QFont QCommandLinkButtonPrivate::titleFont() const Q_Q(const QCommandLinkButton); QFont font = q->font(); if (usingVistaStyle()) { - if (!q->testAttribute(Qt::WA_SetFont)) - font.setPointSizeF(12.0); + font.setPointSizeF(12.0); } else { font.setBold(true); - if (!q->testAttribute(Qt::WA_SetFont)) - font.setPointSizeF(9.0); + font.setPointSizeF(9.0); } - return font; + + // Note the font will be resolved against + // QPainters font, so we need to restore the mask + int resolve_mask = font.resolve_mask; + QFont modifiedFont = q->font().resolve(font); + modifiedFont.detach(); + modifiedFont.resolve_mask = resolve_mask; + return modifiedFont; } QFont QCommandLinkButtonPrivate::descriptionFont() const { Q_Q(const QCommandLinkButton); QFont font = q->font(); - if (!q->testAttribute(Qt::WA_SetFont)) - font.setPointSizeF(9.0); - return font; + font.setPointSizeF(9.0); + + // Note the font will be resolved against + // QPainters font, so we need to restore the mask + int resolve_mask = font.resolve_mask; + QFont modifiedFont = q->font().resolve(font); + modifiedFont.detach(); + modifiedFont.resolve_mask = resolve_mask; + return modifiedFont; } QRect QCommandLinkButtonPrivate::titleRect() const |