diff options
Diffstat (limited to 'src/gui')
48 files changed, 1016 insertions, 413 deletions
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..ff2fb85 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(qreal(0.7)) {} + + QPixmapBlurFilter blurFilter; + int colorTable[256]; + int brightness; + qreal strength; +}; + QT_END_NAMESPACE #endif // QGRAPHICSEFFECT_P_H diff --git a/src/gui/embedded/qscreenvfb_qws.cpp b/src/gui/embedded/qscreenvfb_qws.cpp index 19d4fa8..d71336d 100644 --- a/src/gui/embedded/qscreenvfb_qws.cpp +++ b/src/gui/embedded/qscreenvfb_qws.cpp @@ -196,7 +196,7 @@ bool QVFbScreen::connect(const QString &displaySpec) if (displayArgs.contains(QLatin1String("Gray"))) grayscale = true; - key_t key = ftok(QByteArray(QT_VFB_MOUSE_PIPE).replace("%1", QByteArray::number(displayId)), 'b'); + key_t key = ftok(QT_VFB_MOUSE_PIPE(displayId).toLocal8Bit(), 'b'); if (key == -1) return false; @@ -330,8 +330,7 @@ void QVFbScreen::disconnect() bool QVFbScreen::initDevice() { #ifndef QT_NO_QWS_MOUSE_QVFB - const QString mouseDev = QString::fromLatin1(QT_VFB_MOUSE_PIPE) - .arg(displayId); + const QString mouseDev = QT_VFB_MOUSE_PIPE(displayId); d_ptr->mouse = new QVFbMouseHandler(QLatin1String("QVFbMouse"), mouseDev); qwsServer->setDefaultMouse("None"); if (d_ptr->mouse) @@ -339,8 +338,7 @@ bool QVFbScreen::initDevice() #endif #if !defined(QT_NO_QWS_KBD_QVFB) && !defined(QT_NO_QWS_KEYBOARD) - const QString keyboardDev = QString::fromLatin1(QT_VFB_KEYBOARD_PIPE) - .arg(displayId); + const QString keyboardDev = QT_VFB_KEYBOARD_PIPE(displayId); d_ptr->keyboard = new QVFbKeyboardHandler(keyboardDev); qwsServer->setDefaultKeyboard("None"); #endif diff --git a/src/gui/embedded/qsoundqss_qws.cpp b/src/gui/embedded/qsoundqss_qws.cpp index 6bac8dc..b859be5 100644 --- a/src/gui/embedded/qsoundqss_qws.cpp +++ b/src/gui/embedded/qsoundqss_qws.cpp @@ -67,6 +67,8 @@ #include <qdebug.h> +#include <qvfbhdr.h> + extern int errno; QT_BEGIN_NAMESPACE @@ -79,7 +81,6 @@ QT_BEGIN_NAMESPACE static int sound_speed = 44100; #ifndef QT_NO_QWS_SOUNDSERVER extern int qws_display_id; -#define SOUND_PIPE "/tmp/.qt_soundserver-%1" #endif static char *zeroMem = 0; @@ -708,7 +709,7 @@ protected: #ifndef QT_NO_QWS_SOUNDSERVER QWSSoundServerSocket::QWSSoundServerSocket(QObject *parent) : - QWSServerSocket(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id), parent) + QWSServerSocket(QT_VFB_SOUND_PIPE(qws_display_id), parent) { connect(this, SIGNAL(newConnection()), this, SLOT(newConnection())); } @@ -716,7 +717,7 @@ QWSSoundServerSocket::QWSSoundServerSocket(QObject *parent) : #ifdef QT3_SUPPORT QWSSoundServerSocket::QWSSoundServerSocket(QObject *parent, const char *name) : - QWSServerSocket(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id), parent) + QWSServerSocket(QT_VFB_SOUND_PIPE(qws_display_id), parent) { if (name) setObjectName(QString::fromAscii(name)); @@ -1395,7 +1396,7 @@ void QWSSoundServer::translateSoundCompleted( int, int sid ) QWSSoundClient::QWSSoundClient(QObject* parent) : QWSSocket(parent) { - connectToLocalFile(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id)); + connectToLocalFile(QT_VFB_SOUND_PIPE(qws_display_id)); QObject::connect(this,SIGNAL(readyRead()), this,SLOT(tryReadCommand())); if( state() == QWS_SOCK_BASE::ConnectedState ) QTimer::singleShot(1, this, SIGNAL(connected())); @@ -1409,7 +1410,7 @@ QWSSoundClient::~QWSSoundClient( ) void QWSSoundClient::reconnect() { - connectToLocalFile(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id)); + connectToLocalFile(QT_VFB_SOUND_PIPE(qws_display_id)); if( state() == QWS_SOCK_BASE::ConnectedState ) emit connected(); else emit error( QTcpSocket::ConnectionRefusedError ); } diff --git a/src/gui/embedded/qvfbhdr.h b/src/gui/embedded/qvfbhdr.h index 73e08e0..f02286e 100644 --- a/src/gui/embedded/qvfbhdr.h +++ b/src/gui/embedded/qvfbhdr.h @@ -52,9 +52,22 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) -#define QT_VFB_MOUSE_PIPE "/tmp/.qtvfb_mouse-%1" -#define QT_VFB_KEYBOARD_PIPE "/tmp/.qtvfb_keyboard-%1" -#define QT_VFB_MAP "/tmp/.qtvfb_map-%1" +#ifndef QT_QWS_TEMP_DIR +#define QT_QWS_TEMP_DIR "/tmp" +#endif + +#define QT_VFB_DATADIR(DISPLAY) QString("%1/qtembedded-%2-%3") \ + .arg(QT_QWS_TEMP_DIR).arg(getuid()).arg(DISPLAY) + +#define QT_VFB_MOUSE_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ + .append("/qtvfb_mouse") +#define QT_VFB_KEYBOARD_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ + .append("/qtvfb_keyboard") +#define QT_VFB_MAP(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ + .append("/qtvfb_map") +#define QT_VFB_SOUND_PIPE(DISPLAY) QT_VFB_DATADIR(DISPLAY) \ + .append("/qt_soundserver") +#define QTE_PIPE "QtEmbedded" struct QVFbHeader { diff --git a/src/gui/embedded/qwscommand_qws_p.h b/src/gui/embedded/qwscommand_qws_p.h index d92c6af..f986a9d 100644 --- a/src/gui/embedded/qwscommand_qws_p.h +++ b/src/gui/embedded/qwscommand_qws_p.h @@ -75,8 +75,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) -#define QTE_PIPE "QtEmbedded-%1" - class QRect; /********************************************************************* diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index d7a7bd2..0690690 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -186,6 +186,49 @@ high z-values. Stacking order applies to sibling items; parents are always drawn before their children. + \section1 Sorting + + All items are drawn in a defined, stable order, and this same order decides + which items will receive mouse input first when you click on the scene. + Normally you don't have to worry about sorting, as the items follow a + "natural order", following the logical structure of the scene. + + An item's children are stacked on top of the parent, and sibling items are + stacked by insertion order (i.e., in the same order that they were either + added to the scene, or added to the same parent). If you add item A, and + then B, then B will be on top of A. If you then add C, the items' stacking + order will be A, then B, then C. + + \image graphicsview-zorder.png + + This example shows the stacking order of all limbs of the robot from the + \l{graphicsview/dragdroprobot}{Drag and Drop Robot} example. The torso is + the root item (all other items are children or descendants of the torso), + so it is drawn first. Next, the head is drawn, as it is the first item in + the torso's list of children. Then the upper left arm is drawn. As the + lower arm is a child of the upper arm, the lower arm is then drawn, + followed by the upper arm's next sibling, which is the upper right arm, and + so on. + + For advanced users, there are ways to alter how your items are sorted: + + \list + \o You can call setZValue() on an item to explicitly stack it on top of, or + under, other sibling items. The default Z value for an item is 0. Items + with the same Z value are stacked by insertion order. + + \o You can call stackBefore() to reorder the list of children. This will + directly modify the insertion order. + + \o You can set the ItemStacksBehindParent flag to stack a child item behind + its parent. + \endlist + + The stacking order of two sibling items also counts for each item's + children and descendant items. So if one item is on top of another, then + all its children will also be on top of all the other item's children as + well. + \section1 Events QGraphicsItem receives events from QGraphicsScene through the virtual @@ -564,6 +607,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 @@ -1472,10 +1530,12 @@ QList<QGraphicsItem *> QGraphicsItem::children() const /*! \since 4.4 - Returns a list of this item's children. The items are returned in no - particular order. + Returns a list of this item's children. - \sa setParentItem() + The items are sorted by stacking order. This takes into account both the + items' insertion order and their Z-values. + + \sa setParentItem(), zValue(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsItem::childItems() const { @@ -1649,6 +1709,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 +1795,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 +2085,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 +2108,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 +2939,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 +3457,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 +3938,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 +4072,7 @@ void QGraphicsItem::scale(qreal sx, qreal sy) /*! \obsolete - Use + Use \code setTransform(QTransform().shear(sh, sv), true); @@ -3936,7 +4094,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 @@ -3977,12 +4135,12 @@ void QGraphicsItem::advance(int phase) } /*! - Returns the Z-value, or the elevation, of the item. The Z-value decides - the stacking order of sibling (neighboring) items. + Returns the Z-value of the item. The Z-value affects the stacking order of + sibling (neighboring) items. The default Z-value is 0. - \sa setZValue() + \sa setZValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent */ qreal QGraphicsItem::zValue() const { @@ -3990,33 +4148,18 @@ qreal QGraphicsItem::zValue() const } /*! - Sets the Z-value, or the elevation, of the item, to \a z. The elevation - decides the stacking order of sibling (neighboring) items. An item of high - Z-value will be drawn on top of an item with a lower Z-value if they share - the same parent item. In addition, children of an item will always be - drawn on top of the parent, regardless of the child's Z-value. Sibling - items that share the same Z-value will be drawn in order of insertion; the - last inserted child is stacked above previous children. + Sets the Z-value of the item to \a z. The Z value decides the stacking + order of sibling (neighboring) items. A sibling item of high Z value will + always be drawn on top of another sibling item with a lower Z value. - \img graphicsview-zorder.png - - Children of different parents are stacked according to the Z-value of - each item's ancestor item which is an immediate child of the two - items' closest common ancestor. For example, a robot item might - define a torso item as the parent of a head item, two arm items, - and two upper-leg items. The upper-leg items would each be parents - of one lower-leg item, and each lower-leg item would be parents of - one foot item. The stacking order of the feet is the same as the - stacking order of each foot's ancestor that is an immediate child - of the two feet's common ancestor (i.e., the torso item); so the - feet are stacked in the same order as the upper-leg items, - regardless of each foot's Z-value. + If you restore the Z value, the item's insertion order will decide its + stacking order. The Z-value does not affect the item's size in any way. The default Z-value is 0. - \sa zValue() + \sa zValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent */ void QGraphicsItem::setZValue(qreal z) { @@ -4079,12 +4222,13 @@ void QGraphicsItemPrivate::ensureSequentialSiblingIndex() The \a sibling must have the same Z value as this item, otherwise calling this function will have no effect. - By default, all items are stacked by insertion order (i.e., the first item - you add is drawn before the next item you add). If two items' Z values are - different, then the item with the highest Z value is drawn on top. When the - Z values are the same, the insertion order will decide the stacking order. + By default, all sibling items are stacked by insertion order (i.e., the + first item you add is drawn before the next item you add). If two items' Z + values are different, then the item with the highest Z value is drawn on + top. When the Z values are the same, the insertion order will decide the + stacking order. - \sa setZValue(), ItemStacksBehindParent + \sa setZValue(), ItemStacksBehindParent, {QGraphicsItem#Sorting}{Sorting} */ void QGraphicsItem::stackBefore(const QGraphicsItem *sibling) { @@ -4446,7 +4590,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 +6739,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 +7164,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 +10668,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..1226722 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(); @@ -1723,9 +1760,9 @@ QRectF QGraphicsScene::itemsBoundingRect() const } /*! - Returns a list of all items on the scene, in no particular order. + Returns a list of all items in the scene in descending stacking order. - \sa addItem(), removeItem() + \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items() const { @@ -1735,9 +1772,9 @@ QList<QGraphicsItem *> QGraphicsScene::items() const /*! Returns an ordered list of all items on the scene. \a order decides the - sorting. + stacking order. - \sa addItem(), removeItem() + \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const { @@ -1756,7 +1793,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const contains items that ignore transformations. Use the overload that takes a QTransform instead. - \sa itemAt() + \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const { @@ -1778,7 +1815,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const contains items that ignore transformations. Use the overload that takes a QTransform instead. - \sa itemAt() + \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const { @@ -1799,20 +1836,20 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe */ /*! - \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, - Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \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. */ /*! + \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const \overload \obsolete @@ -1826,7 +1863,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe contains items that ignore transformations. Use the overload that takes a QTransform instead. - \sa itemAt() + \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const { @@ -1835,6 +1872,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS } /*! + \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const \overload \obsolete @@ -1848,7 +1886,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS contains items that ignore transformations. Use the overload that takes a QTransform instead. - \sa itemAt() + \sa itemAt(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const { @@ -1857,10 +1895,11 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemS } /*! + \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const \since 4.6 - Returns all visible items that, depending on \a mode, are at the specified \a pos - in a list sorted using \a order. + \brief Returns all visible items that, depending on \a mode, are at + the specified \a pos in a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with \a pos are returned. @@ -1868,7 +1907,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemS \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(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1878,11 +1917,13 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti } /*! + \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. @@ -1890,7 +1931,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti \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(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1900,11 +1941,13 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti } /*! + \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. @@ -1912,7 +1955,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti \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(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1922,11 +1965,13 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS } /*! + \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. @@ -1934,7 +1979,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS \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(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1949,10 +1994,11 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemS detection is determined by \a mode. By default, all items whose shape intersects \a item or is contained inside \a item's shape are returned. - The items are returned in descending Z order (i.e., the first item in the - list is the top-most item, and the last item is the bottom-most item). + The items are returned in descending stacking order (i.e., the first item + in the list is the uppermost item, and the last item is the lowermost + item). - \sa items(), itemAt(), QGraphicsItem::collidesWithItem() + \sa items(), itemAt(), QGraphicsItem::collidesWithItem(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode) const @@ -1979,13 +2025,11 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item, Returns the topmost visible item at the specified \a position, or 0 if there are no items at this position. - \note The topmost item is the one with the highest Z-value. - 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 items(), collidingItems(), QGraphicsItem::setZValue() + \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting} */ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const { @@ -2002,10 +2046,8 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const \a deviceTransform is the transformation that applies to the view, and needs to be provided if the scene contains items that ignore transformations. - \note The topmost item is the one with the highest Z-value. - - \sa items(), collidingItems(), QGraphicsItem::setZValue() - */ + \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting} +*/ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const { QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape, @@ -2026,8 +2068,6 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform This convenience function is equivalent to calling \c {itemAt(QPointF(x, y), deviceTransform)}. - - \note The topmost item is the one with the highest Z-value. */ /*! @@ -2044,8 +2084,6 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform This function is deprecated and returns incorrect results if the scene contains items that ignore transformations. Use the overload that takes a QTransform instead. - - \note The topmost item is the one with the highest Z-value. */ /*! @@ -2324,7 +2362,7 @@ void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group) in the scene, then the item will be activated. \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(), - addRect(), addText(), addWidget() + addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting} */ void QGraphicsScene::addItem(QGraphicsItem *item) { @@ -2403,6 +2441,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 +3245,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 +3272,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 +3647,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 +3724,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 +3760,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 +3787,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 +3819,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 +5475,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 +5550,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve break; } } + if (item->isPanel()) + break; } // If nobody could take focus, clear it. @@ -5518,6 +5577,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } break; } + if (item->isPanel()) + break; } touchEvent->setAccepted(eventAccepted); @@ -5536,6 +5597,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/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 98b2c9c..32747cc 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2016,9 +2016,11 @@ void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect } /*! - Returns a list of all the items in the associated scene. + Returns a list of all the items in the associated scene, in descending + stacking order (i.e., the first item in the returned list is the uppermost + item). - \sa QGraphicsScene::items() + \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsView::items() const { @@ -2030,9 +2032,9 @@ QList<QGraphicsItem *> QGraphicsView::items() const /*! Returns a list of all the items at the position \a pos in the view. The - items are listed in descending Z order (i.e., the first item in the list - is the top-most item, and the last item is the bottom-most item). \a pos - is in viewport coordinates. + items are listed in descending stacking order (i.e., the first item in the + list is the uppermost item, and the last item is the lowermost item). \a + pos is in viewport coordinates. This function is most commonly called from within mouse event handlers in a subclass in QGraphicsView. \a pos is in untransformed viewport @@ -2040,7 +2042,7 @@ QList<QGraphicsItem *> QGraphicsView::items() const \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5 - \sa QGraphicsScene::items(), QGraphicsItem::zValue() + \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const { @@ -2082,7 +2084,10 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a rect are returned. - \sa itemAt(), items(), mapToScene() + The items are sorted in descending stacking order (i.e., the first item in + the returned list is the uppermost item). + + \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const { @@ -2110,7 +2115,10 @@ QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelection The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a polygon are returned. - \sa itemAt(), items(), mapToScene() + The items are sorted by descending stacking order (i.e., the first item in + the returned list is the uppermost item). + + \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const { @@ -2130,7 +2138,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a path are returned. - \sa itemAt(), items(), mapToScene() + \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} */ QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const { @@ -2149,7 +2157,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSe \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6 - \sa items() + \sa items(), {QGraphicsItem#Sorting}{Sorting} */ QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const { diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index dccc691..4938442 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -476,9 +476,9 @@ void QS60PixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags flags sourceImage = img.convertToFormat(QImage::Format_MonoLSB); } else { if (img.depth() == 1) { - image = img.hasAlphaChannel() - ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) - : img.convertToFormat(QImage::Format_RGB32); + sourceImage = img.hasAlphaChannel() + ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) + : img.convertToFormat(QImage::Format_RGB32); } else { QImage::Format opaqueFormat = QNativeImage::systemFormat(); 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.cpp b/src/gui/kernel/qapplication.cpp index df5097b..044fedd 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -925,7 +925,7 @@ void QApplicationPrivate::initialize() graphics_system = QGraphicsSystemFactory::create(graphics_system_name); #endif #ifndef QT_NO_WHEELEVENT -#ifdef QT_MAC_USE_COCOA +#ifdef Q_OS_MAC QApplicationPrivate::wheel_scroll_lines = 1; #else QApplicationPrivate::wheel_scroll_lines = 3; @@ -3071,7 +3071,7 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) qt_button_down = 0; // Send enter/leave events followed by a mouse move on the entered widget. - QMouseEvent e(QEvent::MouseMove, pos, globalPos, Qt::NoButton, mouse_buttons, modifier_buttons); + QMouseEvent e(QEvent::MouseMove, pos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver); #endif // QT_NO_CURSOR } diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index c294e62..a95ae9d 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1686,13 +1686,15 @@ 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; + wheel_deltaX = mdelt * scrollFactor; + mdelt = 0; GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); - wheel_deltaY = mdelt; + wheel_deltaY = mdelt * scrollFactor; GetEventParameter(event, kEventParamEventRef, typeEventRef, 0, sizeof(compatibilityEvent), 0, &compatibilityEvent); } else if (ekind == kEventMouseWheelMoved) { @@ -1704,10 +1706,14 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event EventMouseWheelAxis axis; 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: + int scrollFactor = 120 * qMin(5, qAbs(mdelt)); if (axis == kEventMouseWheelAxisX) - wheel_deltaX = mdelt * 120; + wheel_deltaX = mdelt * scrollFactor; else - wheel_deltaY = mdelt * 120; + wheel_deltaY = mdelt * scrollFactor; } } @@ -2660,7 +2666,11 @@ int QApplication::keyboardInputInterval() void QApplication::setWheelScrollLines(int n) { - QApplicationPrivate::wheel_scroll_lines = 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; } int QApplication::wheelScrollLines() diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp index e9284f7..01c64f1 100644 --- a/src/gui/kernel/qapplication_qws.cpp +++ b/src/gui/kernel/qapplication_qws.cpp @@ -110,6 +110,8 @@ #include <sys/stat.h> #include <sys/types.h> +#include <qvfbhdr.h> + #ifndef QT_NO_QWS_MULTIPROCESS #ifdef QT_NO_QSHM #include <sys/ipc.h> @@ -199,14 +201,9 @@ QString qws_dataDir() static QString result; if (!result.isEmpty()) return result; - QByteArray dataDir; -#ifdef QT_QWS_TEMP_DIR - dataDir = QT_QWS_TEMP_DIR; -#else - dataDir = "/tmp"; -#endif - dataDir += "/qtembedded-"; - dataDir += QByteArray::number(qws_display_id); + result = QT_VFB_DATADIR(qws_display_id); + QByteArray dataDir = result.toLocal8Bit(); + if (QT_MKDIR(dataDir, 0700)) { if (errno != EEXIST) { qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData()); @@ -227,16 +224,15 @@ QString qws_dataDir() if ((buf.st_mode & 0677) != 0600) qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData()); #endif - dataDir += '/'; - result = QString::fromLocal8Bit(dataDir); + result.append("/"); return result; } // Get the filename of the pipe Qt for Embedded Linux uses for server/client comms Q_GUI_EXPORT QString qws_qtePipeFilename() { - return (qws_dataDir() + QString::fromLatin1(QTE_PIPE).arg(qws_display_id)); + return (qws_dataDir().append(QTE_PIPE)); } static void setMaxWindowRect(const QRect &rect) diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 1bb07bc..af9fe92 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; } @@ -865,8 +868,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) @@ -910,6 +928,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 @@ -1047,6 +1090,10 @@ void qt_init(QApplicationPrivate * /* priv */, int) } #endif + QFont systemFont; + systemFont.setFamily(systemFont.defaultFamily()); + QApplicationPrivate::setSystemFont(systemFont); + /* ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag int argc = priv->argc; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 6ecd535..44f82b6 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; } @@ -2028,13 +1967,22 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam // where it got it from; it would simply get a 0 value as the old focus widget. #ifdef Q_WS_WINCE { - if (widget->windowState() & Qt::WindowMinimized) { - if (widget->windowState() & Qt::WindowMaximized) - widget->showMaximized(); - else - widget->show(); +#ifdef Q_WS_WINCE_WM + // On Windows mobile we do not receive WM_SYSCOMMAND / SC_MINIMIZE messages. + // Thus we have to unset the minimized state explicitly. We must do this for all + // top-level widgets, because we get the HWND of a random widget here. + foreach (QWidget* tlw, QApplication::topLevelWidgets()) { + if (tlw->isMinimized()) + tlw->setWindowState(tlw->windowState() & ~Qt::WindowMinimized); } #else + // On Windows CE we do not receive WM_SYSCOMMAND / SC_MINIMIZE messages. + // Thus we have to unset the minimized state explicitly. + if (widget->windowState() & Qt::WindowMinimized) + widget->setWindowState(widget->windowState() & ~Qt::WindowMinimized); +#endif // Q_WS_WINCE_WM + +#else if (!(widget->windowState() & Qt::WindowMinimized)) { #endif // Ignore the activate message send by WindowsXP to a minimized window diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index f482d1c..b1c5fc5 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -789,18 +789,22 @@ extern "C" { const EventRef carbonEvent = (EventRef)[theEvent eventRef]; const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; if (carbonEventKind == kEventMouseScroll) { - // The mouse device containts pixel scroll - // wheel support (Mighty Mouse, Trackpad) - deltaX = (int)[theEvent deviceDeltaX] * 120; - deltaY = (int)[theEvent deviceDeltaY] * 120; - deltaZ = (int)[theEvent deviceDeltaZ] * 120; + // 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 * qMax(0.6, 1.1 - qAbs([theEvent deltaX])); - deltaY = [theEvent deltaY] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaY])); - deltaZ = [theEvent deltaZ] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaZ])); + deltaX = [theEvent deltaX] * scrollFactor; + deltaY = [theEvent deltaY] * scrollFactor; + deltaZ = [theEvent deltaZ] * scrollFactor; } if (deltaX != 0) { 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/qevent.cpp b/src/gui/kernel/qevent.cpp index ce64c68..7b9cc9a 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3566,7 +3566,7 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) Qt::WA_AcceptTouchEvents attribute set and graphics items need to have the \l{QGraphicsItem::setAcceptTouchEvents()}{acceptTouchEvents} attribute set to true. - When using QAbstractScrollArea based widgets, you should enabled the Qt::WA_AcceptTouchEvents + When using QAbstractScrollArea based widgets, you should enable the Qt::WA_AcceptTouchEvents attribute on the scroll area's \l{QAbstractScrollArea::viewport()}{viewport}. Similarly to QMouseEvent, Qt automatically grabs each touch point on the first press inside a diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index 048780e..58e12ee 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -329,17 +329,14 @@ void qt_wince_maximize(QWidget *widget) void qt_wince_minimize(HWND hwnd) { - uint exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE); - uint style = GetWindowLongW(hwnd, GWL_STYLE); - RECT rect; - RECT crect = {0,0,0,0}; - GetWindowRect(hwnd, &rect); - AdjustWindowRectEx(&crect, style & ~WS_OVERLAPPED, FALSE, exstyle); - MoveWindow(hwnd, rect.left - crect.left, rect.top - crect.top, 0, 0, true); - SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NODRAG); #ifdef Q_OS_WINCE_WM ShowWindow(hwnd, SW_HIDE); #else + if (!IsWindowVisible(hwnd)) { + // Hack for an initial showMinimized. + // Without it, our widget doesn't appear in the task bar. + ShowWindow(hwnd, SW_SHOW); + } ShowWindow(hwnd, SW_MINIMIZE); #endif } diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp index 402d88e..10958f3 100644 --- a/src/gui/kernel/qkeymapper_win.cpp +++ b/src/gui/kernel/qkeymapper_win.cpp @@ -433,6 +433,23 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::NoModifier, // Fall-back to raw Key_* }; +/** + Remap return or action key to select key for windows mobile. +*/ +inline int winceKeyBend(int keyCode) +{ +#ifdef Q_OS_WINCE_WM + // remap return or action key to select key for windows mobile. + // will be changed to a table remapping function in the next version (4.6/7). + if (keyCode == 13) + return Qt::Key_Select; + else + return KeyTbl[keyCode]; +#else + return KeyTbl[keyCode]; +#endif +} + #if defined(Q_OS_WINCE) // Use the KeyTbl to resolve a Qt::Key out of the virtual keys. // In case it is not resolvable, continue using the virtual key itself. @@ -472,7 +489,7 @@ static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, // Qt::Key_*'s are not encoded below 0x20, so try again, and DEL keys (0x7f) is encoded with a // proper Qt::Key_ code if (code < 0x20 || code == 0x7f) // Handles res==0 too - code = KeyTbl[vk]; + code = winceKeyBend(vk); if (isDeadkey) *isDeadkey = (res == -1); @@ -482,7 +499,7 @@ static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, Q_GUI_EXPORT int qt_translateKeyCode(int vk) { - int code = (vk < 0 || vk > 255) ? 0 : KeyTbl[vk]; + int code = winceKeyBend((vk < 0 || vk > 255) ? 0 : vk); return code == Qt::Key_unknown ? 0 : code; } @@ -689,7 +706,7 @@ void QKeyMapperPrivate::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 keyLayout[vk_key]->qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x80 : 0; // Add a fall back key for layouts which don't do composition and show non-latin1 characters - int fallbackKey = KeyTbl[vk_key]; + int fallbackKey = winceKeyBend(vk_key); if (!fallbackKey || fallbackKey == Qt::Key_unknown) { fallbackKey = 0; if (vk_key != keyLayout[vk_key]->qtKey[0] && vk_key < 0x5B && vk_key > 0x2F) @@ -898,7 +915,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool // ..also if we're typing numbers on the keypad, while holding down the Alt modifier. int code = 0; if (isNumpad && (nModifiers & AltAny)) { - code = KeyTbl[msg.wParam]; + code = winceKeyBend(msg.wParam); } else if (!isDeadKey) { unsigned char kbdBuffer[256]; // Will hold the complete keyboard state GetKeyboardState(kbdBuffer); 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 e2de148..0b75b06 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1177,10 +1177,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) if (f & Qt::MSWindowsOwnDC) q->setAttribute(Qt::WA_NativeWindow); -#ifdef Q_WS_WINCE - data.window_state_internal = 0; -#endif - q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute() adjustQuitOnCloseAttribute(); @@ -8336,12 +8332,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(); diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 7e250e2..76418af 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -133,9 +133,6 @@ public: int alloc_region_index; // int alloc_region_revision; #endif -#if defined(Q_WS_WINCE) - uint window_state_internal : 4; -#endif QRect wrect; }; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 1d67b6c..c06ef73 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); void activateSymbianWindow(); #endif diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index cb14e53..3328cee 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; @@ -442,15 +448,15 @@ void QWidgetPrivate::show_sys() } if (q->internalWinId()) { - - WId id = q->internalWinId(); if (!extra->activated) - activateSymbianWindow(); + activateSymbianWindow(); + + QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId()); 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 @@ -481,11 +487,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(); @@ -501,36 +507,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() @@ -617,7 +594,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); @@ -627,7 +604,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); } @@ -1144,17 +1121,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; @@ -1181,7 +1158,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 @@ -1209,7 +1186,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 @@ -1319,8 +1296,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/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index c705e2a..a0982f4 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -1402,7 +1402,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) SetWindowPlacement(q->internalWinId(), &wndpl); } else { #else - if (data.window_state_internal & Qt::WindowMaximized) { + if (data.window_state & Qt::WindowMaximized) { qt_wince_maximize(q); } else { #endif diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp index 32e8e7f..4a0d30c 100644 --- a/src/gui/kernel/qwidget_wince.cpp +++ b/src/gui/kernel/qwidget_wince.cpp @@ -416,6 +416,10 @@ void QWidgetPrivate::show_sys() { SetWindowLong(q->internalWinId(), GWL_STYLE, style | WS_MAXIMIZEBOX); } } else +#else + // Imitate minimizing on Windows mobile by hiding the widget. + if (q->isMinimized()) + sm = SW_HIDE; #endif if (q->isHidden()) { sm = SW_HIDE; @@ -428,8 +432,7 @@ void QWidgetPrivate::show_sys() { sm = SW_SHOWNOACTIVATE; } - if (!(data.window_state & Qt::WindowMinimized)) - ShowWindow(q->internalWinId(), sm); + ShowWindow(q->internalWinId(), sm); if (q->isMaximized() && q->isWindow()) qt_wince_maximize(q); @@ -438,7 +441,7 @@ void QWidgetPrivate::show_sys() { if (!qt_wince_is_mobile() && q->isFullScreen()) { HWND handle = FindWindow(L"HHTaskBar", L""); if (handle) { - ShowWindow(handle, 0); + ShowWindow(handle, SW_HIDE); EnableWindow(handle, false); } } @@ -468,21 +471,15 @@ void QWidget::setWindowState(Qt::WindowStates newstate) return; int max = SW_SHOWNORMAL; - int min = SW_SHOWNOACTIVATE; - int normal = SW_SHOWNOACTIVATE; if ((oldstate & Qt::WindowMinimized) && !(newstate & Qt::WindowMinimized)) newstate |= Qt::WindowActive; - if (newstate & Qt::WindowActive) { - max = SW_SHOWNORMAL; - min = SW_SHOWNORMAL; + if (newstate & Qt::WindowActive) normal = SW_SHOWNORMAL; - } if (isWindow()) { createWinId(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - data->window_state_internal = newstate; // Ensure the initial size is valid, since we store it as normalGeometry below. if ((!testAttribute(Qt::WA_Resized) && !isVisible())) adjustSize(); @@ -556,13 +553,11 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } } if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) { - if (isVisible()) { - ShowWindow(internalWinId(), (newstate & Qt::WindowMinimized) ? min : - (newstate & Qt::WindowMaximized) ? max : normal); - if (newstate & Qt::WindowMaximized) - qt_wince_maximize(this); if (newstate & Qt::WindowMinimized) qt_wince_minimize(internalWinId()); + else if (newstate & Qt::WindowMaximized) { + ShowWindow(internalWinId(), max); + qt_wince_maximize(this); } } if ((newstate & Qt::WindowMaximized) && !(newstate & Qt::WindowFullScreen)) { @@ -577,7 +572,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } } data->window_state = newstate; - data->window_state_internal = newstate; QWindowStateChangeEvent e(oldstate); QApplication::sendEvent(this, &e); } @@ -588,7 +582,7 @@ void QWidgetPrivate::deleteSysExtra() if (!qt_wince_is_mobile() && q->isFullScreen()) { HWND handle = FindWindow(L"HHTaskBar", L""); if (handle) { - ShowWindow(handle, 1); + ShowWindow(handle, SW_SHOWNORMAL); EnableWindow(handle, true); } } 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_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 131d8bc..cde48d8 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -635,8 +635,18 @@ bool QS60StylePrivate::isToolBarBackground() QPoint qt_s60_fill_background_offset(const QWidget *targetWidget) { CCoeControl *control = targetWidget->effectiveWinId(); - TPoint globalPos = control ? control->PositionRelativeToScreen() : TPoint(0,0); - return QPoint(globalPos.iX, globalPos.iY); + TPoint pos(0,0); + if (control) { + // FIXME properly: S60 3.1 has a bug that CCoeControl::PositionRelativeToScreen sometimes + // freezes the device, possibly in cases where we run out of memory. + // We use CCoeControl::Position instead in S60 3.1, which returns same values + // in most cases. + if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1) + pos = control->Position(); + else + pos = control->PositionRelativeToScreen(); + } + return QPoint(pos.iX, pos.iY); } QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX( @@ -1137,11 +1147,11 @@ QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, const QSize &size, SkinElementFlags flags) { QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - + QPixmap result = (flags & SF_ColorSkinned)? QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, flags) : QS60StyleModeSpecifics::skinnedGraphics(part, size, flags); - + lock.relock(); if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledPartGraphic(part)) { 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/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp index a50c105..c3289b4 100644 --- a/src/gui/widgets/qabstractslider.cpp +++ b/src/gui/widgets/qabstractslider.cpp @@ -215,7 +215,8 @@ QT_BEGIN_NAMESPACE QAbstractSliderPrivate::QAbstractSliderPrivate() : minimum(0), maximum(99), singleStep(1), pageStep(10), - value(0), position(0), pressValue(-1), tracking(true), blocktracking(false), pressed(false), + value(0), position(0), pressValue(-1), offset_accumulated(0), tracking(true), + blocktracking(false), pressed(false), invertedAppearance(false), invertedControls(false), orientation(Qt::Horizontal), repeatAction(QAbstractSlider::SliderNoAction) { @@ -691,38 +692,30 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e) e->ignore(); if (e->orientation() != d->orientation && !rect().contains(e->pos())) return; - static qreal offset = 0; - static QAbstractSlider *offset_owner = 0; - if (offset_owner != this){ - offset_owner = this; - offset = 0; - } - // On Mac/Cocoa, always scroll one step. The mouse wheel acceleration - // is higher than on other systems, so this works well in practice. -#ifdef QT_MAC_USE_COCOA - int step = 1; -#else int step = qMin(QApplication::wheelScrollLines() * d->singleStep, d->pageStep); -#endif if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) step = d->pageStep; - int currentOffset = qRound(qreal(e->delta()) * step / 120); - if (currentOffset == 0) - currentOffset = (e->delta() < 0 ? -1 : 1); - offset += currentOffset; - if (d->invertedControls) - offset = -offset; + qreal currentOffset = qreal(e->delta()) * step / 120; + d->offset_accumulated += d->invertedControls ? -currentOffset : currentOffset; - int prevValue = d->value; - d->position = d->overflowSafeAdd(int(offset)); // value will be updated by triggerAction() + 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 prevValue = d->value; + d->position = d->overflowSafeAdd(int(d->offset_accumulated)); // value will be updated by triggerAction() triggerAction(SliderMove); + if (prevValue == d->value) { - offset = 0; + d->offset_accumulated = 0; } else { - offset -= int(offset); + d->offset_accumulated -= int(d->offset_accumulated); e->accept(); } } diff --git a/src/gui/widgets/qabstractslider_p.h b/src/gui/widgets/qabstractslider_p.h index 071b8df..9324d44 100644 --- a/src/gui/widgets/qabstractslider_p.h +++ b/src/gui/widgets/qabstractslider_p.h @@ -69,6 +69,7 @@ public: void setSteps(int single, int page); int minimum, maximum, singleStep, pageStep, value, position, pressValue; + float offset_accumulated; uint tracking : 1; uint blocktracking :1; uint pressed : 1; 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 diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp index dc78fd5..3fe9bb4 100644 --- a/src/gui/widgets/qtextedit.cpp +++ b/src/gui/widgets/qtextedit.cpp @@ -174,8 +174,13 @@ void QTextEditPrivate::init(const QString &html) if (!html.isEmpty()) control->setHtml(html); +#ifdef Q_OS_MAC + hbar->setSingleStep(1); + vbar->setSingleStep(1); +#else hbar->setSingleStep(20); vbar->setSingleStep(20); +#endif viewport->setBackgroundRole(QPalette::Base); q->setAcceptDrops(true); |