diff options
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/dialogs/qmessagebox.cpp | 24 | ||||
-rw-r--r-- | src/widgets/dialogs/qmessagebox.h | 4 | ||||
-rw-r--r-- | src/widgets/dialogs/qwizard.cpp | 6 | ||||
-rw-r--r-- | src/widgets/dialogs/qwizard_win.cpp | 88 | ||||
-rw-r--r-- | src/widgets/dialogs/qwizard_win_p.h | 10 | ||||
-rw-r--r-- | src/widgets/doc/qtwidgets.qdocconf | 10 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsitem.cpp | 73 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsscene.cpp | 100 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsscene.h | 1 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsscene_p.h | 3 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicswidget_p.cpp | 104 | ||||
-rw-r--r-- | src/widgets/itemviews/qabstractitemview.cpp | 20 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 2 | ||||
-rw-r--r-- | src/widgets/styles/qstyleanimation.cpp | 6 | ||||
-rw-r--r-- | src/widgets/widgets/qlabel.cpp | 14 |
15 files changed, 293 insertions, 172 deletions
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 751fe289bc..e93850c1b7 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1225,6 +1225,30 @@ void QMessageBox::setTextFormat(Qt::TextFormat format) } /*! + \property QMessageBox::textInteractionFlags + \since 5.1 + + Specifies how the label of the message box should interact with user + input. + + The default value depends on the style. + + \sa QStyle::SH_MessageBox_TextInteractionFlags +*/ + +Qt::TextInteractionFlags QMessageBox::textInteractionFlags() const +{ + Q_D(const QMessageBox); + return d->label->textInteractionFlags(); +} + +void QMessageBox::setTextInteractionFlags(Qt::TextInteractionFlags flags) +{ + Q_D(QMessageBox); + d->label->setTextInteractionFlags(flags); +} + +/*! \reimp */ bool QMessageBox::event(QEvent *e) diff --git a/src/widgets/dialogs/qmessagebox.h b/src/widgets/dialogs/qmessagebox.h index c130dee48b..2f8b4576fa 100644 --- a/src/widgets/dialogs/qmessagebox.h +++ b/src/widgets/dialogs/qmessagebox.h @@ -69,6 +69,7 @@ class Q_WIDGETS_EXPORT QMessageBox : public QDialog Q_PROPERTY(QString detailedText READ detailedText WRITE setDetailedText) #endif Q_PROPERTY(QString informativeText READ informativeText WRITE setInformativeText) + Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) public: enum Icon { @@ -186,6 +187,9 @@ public: Qt::TextFormat textFormat() const; void setTextFormat(Qt::TextFormat format); + void setTextInteractionFlags(Qt::TextInteractionFlags flags); + Qt::TextInteractionFlags textInteractionFlags() const; + static StandardButton information(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton); diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 241e9f678a..654ce9cc6b 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -1557,7 +1557,7 @@ void QWizardPrivate::handleAeroStyleChange() _q_updateButtonStates(); if (q->isVisible()) - vistaHelper->setWindowPosHack(); + vistaHelper->updateCustomMargins(); inHandleAeroStyleChange = false; } @@ -2922,6 +2922,10 @@ QWidget *QWizard::sideWidget() const void QWizard::setVisible(bool visible) { Q_D(QWizard); +#if !defined(QT_NO_STYLE_WINDOWSVISTA) + if (visible) + d->vistaHelper->updateCustomMargins(); +#endif if (visible) { if (d->current == -1) restart(); diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp index c78202e866..ef41ca32e8 100644 --- a/src/widgets/dialogs/qwizard_win.cpp +++ b/src/widgets/dialogs/qwizard_win.cpp @@ -49,7 +49,9 @@ #include "qwizard.h" #include "qpaintengine.h" #include "qapplication.h" +#include <QtCore/QVariant> #include <QtGui/QMouseEvent> +#include <QtGui/QWindow> #include <QtWidgets/QDesktopWidget> // Note, these tests are duplicates in qwindowsxpstyle_p.h. @@ -66,6 +68,8 @@ #include <uxtheme.h> +Q_DECLARE_METATYPE(QMargins) + QT_BEGIN_NAMESPACE //DWM related @@ -265,6 +269,26 @@ QVistaHelper::~QVistaHelper() --instanceCount; } +void QVistaHelper::updateCustomMargins() +{ + if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) + return; // Negative margins are not supported on Windows 8. + if (QWindow *window = wizard->windowHandle()) { + // Reduce top frame to zero since we paint it ourselves. + const QMargins customMargins = vistaState() == VistaAero ? + QMargins(0, -titleBarSize(), 0, 0) : QMargins(); + const QVariant customMarginsV = qVariantFromValue(customMargins); + // The dynamic property takes effect when creating the platform window. + window->setProperty("_q_windowsCustomMargins", customMarginsV); + // If a platform window exists, change via native interface. + if (QPlatformWindow *platformWindow = window->handle()) { + QGuiApplication::platformNativeInterface()-> + setWindowProperty(platformWindow, QStringLiteral("WindowsCustomMargins"), + customMarginsV); + } + } +} + bool QVistaHelper::isCompositionEnabled() { bool value = is_vista; @@ -291,6 +315,12 @@ QVistaHelper::VistaState QVistaHelper::vistaState() return cachedVistaState; } +void QVistaHelper::disconnectBackButton() +{ + if (backButton_) // Leave QStyleSheetStyle's connections on destroyed() intact. + backButton_->disconnect(SIGNAL(clicked())); +} + QColor QVistaHelper::basicWindowFrameColor() { DWORD rgb; @@ -402,13 +432,6 @@ bool QVistaHelper::winEvent(MSG* msg, long* result) } break; } -// case WM_NCCALCSIZE: { #fixme: If the frame size is changed, it needs to be communicated to the QWindow. -// NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*)msg->lParam; -// *result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam); -// lpncsp->rgrc[0].top -= (vistaState() == VistaAero ? titleBarSize() : 0); -// -// break; -// } default: LRESULT lResult; // Pass to DWM to handle @@ -449,38 +472,6 @@ void QVistaHelper::mouseEvent(QEvent *event) } } -// The following hack ensures that the titlebar is updated correctly -// when the wizard style changes to and from AeroStyle. Specifically, -// this function causes a Windows message of type WM_NCCALCSIZE to -// be triggered. -void QVistaHelper::setWindowPosHack() -{ - const int x = wizard->geometry().x(); // ignored by SWP_NOMOVE - const int y = wizard->geometry().y(); // ignored by SWP_NOMOVE - const int w = wizard->width(); - const int h = wizard->height(); - HWND handle = QApplicationPrivate::getHWNDForWidget(wizard); - SetWindowPos(handle, 0, x, y, w, h, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED); -} - -// The following hack allows any QWidget subclass to access -// QWidgetPrivate::topData() without being declared as a -// friend by QWidget. -class QHackWidget : public QWidget -{ -public: - Q_DECLARE_PRIVATE(QWidget) - QTLWExtra* topData() { return d_func()->topData(); } -}; - -void QVistaHelper::collapseTopFrameStrut() -{ - QTLWExtra *top = ((QHackWidget *)wizard)->d_func()->topData(); - int x1, y1, x2, y2; - top->frameStrut.getCoords(&x1, &y1, &x2, &y2); - top->frameStrut.setCoords(x1, 0, x2, y2); -} - bool QVistaHelper::handleWinEvent(MSG *message, long *result) { if (message->message == WIZ_WM_THEMECHANGED || message->message == WIZ_WM_DWMCOMPOSITIONCHANGED) @@ -489,12 +480,8 @@ bool QVistaHelper::handleWinEvent(MSG *message, long *result) bool status = false; if (wizard->wizardStyle() == QWizard::AeroStyle && vistaState() == VistaAero) { status = winEvent(message, result); - if (message->message == WM_NCCALCSIZE) { -// if (status) #fixme -// collapseTopFrameStrut(); - } else if (message->message == WM_NCPAINT) { + if (message->message == WM_NCPAINT) wizard->update(); - } } return status; } @@ -789,6 +776,19 @@ int QVistaHelper::titleOffset() return leftMargin() + iconOffset; } +int QVistaHelper::topOffset() +{ + if (vistaState() != VistaAero) + return titleBarSize() + 3; + static const int aeroOffset = + QSysInfo::WindowsVersion == QSysInfo::WV_WINDOWS7 ? + QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13); + int result = aeroOffset; + if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) + result += titleBarSize(); + return result; +} + QT_END_NAMESPACE #endif // QT_NO_STYLE_WINDOWSVISTA diff --git a/src/widgets/dialogs/qwizard_win_p.h b/src/widgets/dialogs/qwizard_win_p.h index 8f1c0d6b01..11dd1f2824 100644 --- a/src/widgets/dialogs/qwizard_win_p.h +++ b/src/widgets/dialogs/qwizard_win_p.h @@ -87,6 +87,7 @@ public: QVistaHelper(QWizard *wizard); ~QVistaHelper(); enum TitleBarChangeType { NormalTitleBar, ExtendedTitleBar }; + void updateCustomMargins(); bool setDWMTitleBar(TitleBarChangeType type); void setTitleBarIconAndCaptionVisible(bool visible); void mouseEvent(QEvent *event); @@ -94,9 +95,8 @@ public: void resizeEvent(QResizeEvent *event); void paintEvent(QPaintEvent *event); QVistaBackButton *backButton() const { return backButton_; } - void disconnectBackButton() { if (backButton_) backButton_->disconnect(); } + void disconnectBackButton(); void hideBackButton() { if (backButton_) backButton_->hide(); } - void setWindowPosHack(); QColor basicWindowFrameColor(); enum VistaState { VistaAero, VistaBasic, Classic, Dirty }; static VistaState vistaState(); @@ -105,10 +105,8 @@ public: return int(QStyleHelper::dpiScaled( QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS7 ? 4 : 6)); } - static int topOffset() { - static int aeroOffset = QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS7 ? - QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13); - return (titleBarSize() + (vistaState() == VistaAero ? aeroOffset : 3)); } + static int topOffset(); + private: static HFONT getCaptionFont(HANDLE hTheme); bool drawTitleText(QPainter *painter, const QString &text, const QRect &rect, HDC hdc); diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf index 062adc7f7c..2cd6887f83 100644 --- a/src/widgets/doc/qtwidgets.qdocconf +++ b/src/widgets/doc/qtwidgets.qdocconf @@ -3,21 +3,21 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) project = QtWidgets description = Qt Widgets Reference Documentation url = http://qt-project.org/doc/qtwidgets -version = 5.0.1 +version = 5.1.0 examplesinstallpath = widgets qhp.projects = QtWidgets qhp.QtWidgets.file = qtwidgets.qhp -qhp.QtWidgets.namespace = org.qt-project.qtwidgets.501 +qhp.QtWidgets.namespace = org.qt-project.qtwidgets.510 qhp.QtWidgets.virtualFolder = qtwidgets qhp.QtWidgets.indexTitle = Qt Widgets qhp.QtWidgets.indexRoot = -qhp.QtWidgets.filterAttributes = qtwidgets 5.0.1 qtrefdoc -qhp.QtWidgets.customFilters.Qt.name = QtWidgets 5.0.1 -qhp.QtWidgets.customFilters.Qt.filterAttributes = qtwidgets 5.0.1 +qhp.QtWidgets.filterAttributes = qtwidgets 5.1.0 qtrefdoc +qhp.QtWidgets.customFilters.Qt.name = QtWidgets 5.1.0 +qhp.QtWidgets.customFilters.Qt.filterAttributes = qtwidgets 5.1.0 qhp.QtWidgets.subprojects = classes qhp.QtWidgets.subprojects.classes.title = C++ Classes diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index ec4a1827ef..f76e89f1a0 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -1867,15 +1867,46 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->scene->d_func()->updateInputMethodSensitivityInViews(); } + if ((flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) { + bool becomesPanel = (flags & ItemIsPanel); + if ((d_ptr->panelModality != NonModal) && d_ptr->scene) { + // update the panel's modal state + if (becomesPanel) + d_ptr->scene->d_func()->enterModal(this); + else + d_ptr->scene->d_func()->leaveModal(this); + } + if (d_ptr->isWidget && (becomesPanel || parentWidget())) { + QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this); + QGraphicsWidget *focusFirst = w; + QGraphicsWidget *focusLast = w; + for (;;) { + QGraphicsWidget *test = focusLast->d_func()->focusNext; + if (!w->isAncestorOf(test) || test == w) + break; + focusLast = test; + } - 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 (becomesPanel) { + // unlink own widgets from focus chain + QGraphicsWidget *beforeMe = w->d_func()->focusPrev; + QGraphicsWidget *afterMe = focusLast->d_func()->focusNext; + beforeMe->d_func()->focusNext = afterMe; + afterMe->d_func()->focusPrev = beforeMe; + focusFirst->d_func()->focusPrev = focusLast; + focusLast->d_func()->focusNext = focusFirst; + if (!isAncestorOf(focusFirst->d_func()->focusNext)) + focusFirst->d_func()->focusNext = w; + } else if (QGraphicsWidget *pw = parentWidget()) { + // link up own widgets to focus chain + QGraphicsWidget *beforeMe = pw; + QGraphicsWidget *afterMe = pw->d_func()->focusNext; + beforeMe->d_func()->focusNext = w; + afterMe->d_func()->focusPrev = focusLast; + w->d_func()->focusPrev = beforeMe; + focusLast->d_func()->focusNext = afterMe; + } + } } if (d_ptr->scene) { @@ -2257,7 +2288,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, scene->d_func()->leaveModal(q_ptr); } if (hasFocus && scene) { - // Hiding the closest non-panel ancestor of the focus item + // Hiding the focus item or the closest non-panel ancestor of the focus item QGraphicsItem *focusItem = scene->focusItem(); bool clear = true; if (isWidget && !focusItem->isPanel()) { @@ -3154,16 +3185,20 @@ void QGraphicsItem::setActive(bool active) // Activate this item. d_ptr->scene->setActivePanel(this); } else { - // Deactivate this item, and reactivate the parent panel, - // or the last active panel (if any). - QGraphicsItem *nextToActivate = 0; - if (d_ptr->parent) - nextToActivate = d_ptr->parent->panel(); - if (!nextToActivate) - nextToActivate = d_ptr->scene->d_func()->lastActivePanel; - if (nextToActivate == this || isAncestorOf(nextToActivate)) - nextToActivate = 0; - d_ptr->scene->setActivePanel(nextToActivate); + QGraphicsItem *activePanel = d_ptr->scene->activePanel(); + QGraphicsItem *thisPanel = panel(); + if (!activePanel || activePanel == thisPanel) { + // Deactivate this item, and reactivate the parent panel, + // or the last active panel (if any). + QGraphicsItem *nextToActivate = 0; + if (d_ptr->parent) + nextToActivate = d_ptr->parent->panel(); + if (!nextToActivate) + nextToActivate = d_ptr->scene->d_func()->lastActivePanel; + if (nextToActivate == this || isAncestorOf(nextToActivate)) + nextToActivate = 0; + d_ptr->scene->setActivePanel(nextToActivate); + } } } } diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index ee65fb8fa6..e14a98f332 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -607,7 +607,7 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) q->removeItem(item->d_ptr->children.at(i)); } - if (!item->d_ptr->inDestructor && item == tabFocusFirst) { + if (!item->d_ptr->inDestructor && !item->parentItem() && item->isWidget()) { QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); widget->d_func()->fixFocusChainBeforeReparenting(0, oldScene, 0); } @@ -742,12 +742,14 @@ void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool durin if (panel == activePanel || (!q->isActive() && !duringActivationEvent)) return; + QGraphicsItem *oldFocusItem = focusItem; + // Deactivate the last active panel. if (activePanel) { if (QGraphicsItem *fi = activePanel->focusItem()) { // Remove focus from the current focus item. if (fi == q->focusItem()) - q->setFocusItem(0, Qt::ActiveWindowFocusReason); + setFocusItemHelper(0, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false); } QEvent event(QEvent::WindowDeactivate); @@ -771,9 +773,23 @@ void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool durin QEvent event(QEvent::WindowActivate); q->sendEvent(panel, &event); - // Set focus on the panel's focus item. - if (QGraphicsItem *focusItem = panel->focusItem()) - focusItem->setFocus(Qt::ActiveWindowFocusReason); + // Set focus on the panel's focus item, or itself if it's + // focusable, or on the first focusable item in the panel's + // focus chain as a last resort. + if (QGraphicsItem *focusItem = panel->focusItem()) { + setFocusItemHelper(focusItem, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false); + } else if (panel->flags() & QGraphicsItem::ItemIsFocusable) { + setFocusItemHelper(panel, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false); + } else if (panel->isWidget()) { + QGraphicsWidget *fw = static_cast<QGraphicsWidget *>(panel)->d_func()->focusNext; + do { + if (fw->focusPolicy() & Qt::TabFocus) { + setFocusItemHelper(fw, Qt::ActiveWindowFocusReason, /* emitFocusChanged = */ false); + break; + } + fw = fw->d_func()->focusNext; + } while (fw != panel); + } } else if (q->isActive()) { // Activate the scene QEvent event(QEvent::WindowActivate); @@ -782,13 +798,23 @@ void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool durin q->sendEvent(item, &event); } } + + emit q->focusItemChanged(focusItem, oldFocusItem, Qt::ActiveWindowFocusReason); } /*! \internal + + \a emitFocusChanged needs to be false when focus passes from one + item to another through setActivePanel(); i.e. when activation + passes from one panel to another, to avoid getting two focusChanged() + emissions; one focusChanged(0, lastFocus), then one + focusChanged(newFocus, 0). Instead setActivePanel() emits the signal + once itself: focusChanged(newFocus, oldFocus). */ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, - Qt::FocusReason focusReason) + Qt::FocusReason focusReason, + bool emitFocusChanged) { Q_Q(QGraphicsScene); if (item == focusItem) @@ -804,10 +830,14 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, // Set focus on the scene if an item requests focus. if (item) { q->setFocus(focusReason); - if (item == focusItem) + if (item == focusItem) { + if (emitFocusChanged) + emit q->focusItemChanged(focusItem, (QGraphicsItem *)0, focusReason); return; + } } + QGraphicsItem *oldFocusItem = focusItem; if (focusItem) { lastFocusItem = focusItem; @@ -848,6 +878,9 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, QFocusEvent event(QEvent::FocusIn, focusReason); sendEvent(item, &event); } + + if (emitFocusChanged) + emit q->focusItemChanged(focusItem, oldFocusItem, focusReason); } /*! @@ -2528,14 +2561,13 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // No first tab focus widget - make this the first tab focus // widget. d->tabFocusFirst = widget; - } else if (!widget->parentWidget()) { + } else if (!widget->parentWidget() && !widget->isPanel()) { // Adding a widget that is not part of a tab focus chain. - QGraphicsWidget *last = d->tabFocusFirst->d_func()->focusPrev; - QGraphicsWidget *lastNew = widget->d_func()->focusPrev; - last->d_func()->focusNext = widget; - widget->d_func()->focusPrev = last; - d->tabFocusFirst->d_func()->focusPrev = lastNew; - lastNew->d_func()->focusNext = d->tabFocusFirst; + QGraphicsWidget *myNewPrev = d->tabFocusFirst->d_func()->focusPrev; + myNewPrev->d_func()->focusNext = widget; + widget->d_func()->focusPrev->d_func()->focusNext = d->tabFocusFirst; + d->tabFocusFirst->d_func()->focusPrev = widget->d_func()->focusPrev; + widget->d_func()->focusPrev = myNewPrev; } } @@ -5329,8 +5361,23 @@ bool QGraphicsScene::focusNextPrevChild(bool next) setFocusItem(d->lastFocusItem, next ? Qt::TabFocusReason : Qt::BacktabFocusReason); return true; } + if (d->activePanel) { + if (d->activePanel->flags() & QGraphicsItem::ItemIsFocusable) { + setFocusItem(d->activePanel, next ? Qt::TabFocusReason : Qt::BacktabFocusReason); + return true; + } + if (d->activePanel->isWidget()) { + QGraphicsWidget *fw = static_cast<QGraphicsWidget *>(d->activePanel)->d_func()->focusNext; + do { + if (fw->focusPolicy() & Qt::TabFocus) { + setFocusItem(fw, next ? Qt::TabFocusReason : Qt::BacktabFocusReason); + return true; + } + } while (fw != d->activePanel); + } + } } - if (!d->tabFocusFirst) { + if (!item && !d->tabFocusFirst) { // No widgets... return false; } @@ -5342,8 +5389,10 @@ bool QGraphicsScene::focusNextPrevChild(bool next) } else { QGraphicsWidget *test = static_cast<QGraphicsWidget *>(item); widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev; - if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev)) + if (!widget->panel() && ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))) { + // Tab out of the scene. return false; + } } QGraphicsWidget *widgetThatHadFocus = widget; @@ -5407,6 +5456,25 @@ bool QGraphicsScene::focusNextPrevChild(bool next) */ /*! + \fn QGraphicsScene::focusChanged(QGraphicsItem *newFocusItem, QGraphicsItem *oldFocusItem, Qt::FocusReason reason) + + This signal is emitted by QGraphicsScene whenever focus changes in the + scene (i.e., when an item gains or loses input focus, or when focus + passes from one item to another). You can connect to this signal if you + need to keep track of when other items gain input focus. It is + particularily useful for implementing virtual keyboards, input methods, + and cursor items. + + \a oldFocusItem is a pointer to the item that previously had focus, or + 0 if no item had focus before the signal was emitted. \a newFocusItem + is a pointer to the item that gained input focus, or 0 if focus was lost. + \a reason is the reason for the focus change (e.g., if the scene was + deactivated while an input field had focus, \a oldFocusItem would point + to the input field item, \a newFocusItem would be 0, and \a reason would be + Qt::ActiveWindowFocusReason. +*/ + +/*! \since 4.4 Returns the scene's style, or the same as QApplication::style() if the diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h index 27337d3a2a..3f00b74f53 100644 --- a/src/widgets/graphicsview/qgraphicsscene.h +++ b/src/widgets/graphicsview/qgraphicsscene.h @@ -292,6 +292,7 @@ Q_SIGNALS: void changed(const QList<QRectF> ®ion); void sceneRectChanged(const QRectF &rect); void selectionChanged(); + void focusItemChanged(QGraphicsItem *newFocus, QGraphicsItem *oldFocus, Qt::FocusReason reason); private: Q_DECLARE_PRIVATE(QGraphicsScene) diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h index 6799a835ac..bcb95c694a 100644 --- a/src/widgets/graphicsview/qgraphicsscene_p.h +++ b/src/widgets/graphicsview/qgraphicsscene_p.h @@ -157,7 +157,8 @@ public: int activationRefCount; int childExplicitActivation; void setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent); - void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason); + void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason, + bool emitFocusChanged = true); QList<QGraphicsWidget *> popupWidgets; void addPopup(QGraphicsWidget *widget); diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp index 4ec215a720..dfebbb5036 100644 --- a/src/widgets/graphicsview/qgraphicswidget_p.cpp +++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp @@ -764,73 +764,59 @@ bool QGraphicsWidgetPrivate::hasDecoration() const void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene) { Q_Q(QGraphicsWidget); - Q_ASSERT(focusNext && focusPrev); - QGraphicsWidget *n = q; //last one in 'new' list - QGraphicsWidget *o = 0; //last one in 'old' list - - QGraphicsWidget *w = focusNext; - - QGraphicsWidget *firstOld = 0; - bool wasPreviousNew = true; - - while (w != q) { - bool isCurrentNew = q->isAncestorOf(w); - if (isCurrentNew) { - if (!wasPreviousNew) { - n->d_func()->focusNext = w; - w->d_func()->focusPrev = n; - } - n = w; - } else /*if (!isCurrentNew)*/ { - if (wasPreviousNew) { - if (o) { - o->d_func()->focusNext = w; - w->d_func()->focusPrev = o; - } else { - firstOld = w; - } - } - o = w; - } - w = w->d_func()->focusNext; - wasPreviousNew = isCurrentNew; - } - - // repair the 'old' chain - if (firstOld) { - o->d_func()->focusNext = firstOld; - firstOld->d_func()->focusPrev = o; + if (q_ptr->isPanel()) { + // panels are never a part of their parent's or ancestors' focus + // chains. so reparenting a panel is easy; there's nothing to + // do. + return; } - // update tabFocusFirst for oldScene if the item is going to be removed from oldScene - if (newParent) - newScene = newParent->scene(); - - if (oldScene && newScene != oldScene) - oldScene->d_func()->tabFocusFirst = (firstOld && firstOld->scene() == oldScene) ? firstOld : 0; - - QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0; - QGraphicsWidget *topLevel = 0; - if (topLevelItem && topLevelItem->isWidget()) - topLevel = static_cast<QGraphicsWidget *>(topLevelItem); + // we're not a panel, so find the first widget in the focus chain + // (this), and the last (this, or the last widget that is still + // a descendent of this). also find the widgets that currently / + // before reparenting point to this widgets' focus chain. + QGraphicsWidget *focusFirst = q; + QGraphicsWidget *focusBefore = focusPrev; + QGraphicsWidget *focusLast = focusFirst; + QGraphicsWidget *focusAfter = focusNext; + do { + if (!q->isAncestorOf(focusAfter)) + break; + focusLast = focusAfter; + } while ((focusAfter = focusAfter->d_func()->focusNext)); - if (topLevel && newParent) { - QGraphicsWidget *last = topLevel->d_func()->focusPrev; - // link last with new chain - last->d_func()->focusNext = q; - focusPrev = last; + if (!parent && oldScene && oldScene != newScene && oldScene->d_func()->tabFocusFirst == q) { + // detach from old scene's top level focus chain. + oldScene->d_func()->tabFocusFirst = (focusAfter != q) ? focusAfter : 0; + } - // link last in chain with - topLevel->d_func()->focusPrev = n; - n->d_func()->focusNext = topLevel; + // detach from current focus chain; skip this widget subtree. + focusBefore->d_func()->focusNext = focusAfter; + focusAfter->d_func()->focusPrev = focusBefore; + + if (newParent) { + // attach to new parent's focus chain as the last element + // in its chain. + QGraphicsWidget *newFocusFirst = newParent; + QGraphicsWidget *newFocusLast = newFocusFirst; + QGraphicsWidget *newFocusAfter = newFocusFirst->d_func()->focusNext; + do { + if (!newParent->isAncestorOf(newFocusAfter)) + break; + newFocusLast = newFocusAfter; + } while ((newFocusAfter = newFocusAfter->d_func()->focusNext)); + + newFocusLast->d_func()->focusNext = q; + focusLast->d_func()->focusNext = newFocusAfter; + newFocusAfter->d_func()->focusPrev = focusLast; + focusPrev = newFocusLast; } else { - // q is the start of the focus chain - n->d_func()->focusNext = q; - focusPrev = n; + // no new parent, so just link up our own prev->last widgets. + focusPrev = focusLast; + focusLast->d_func()->focusNext = q; } - } void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l) diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index ccf3f929af..cb466dfb4b 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -3816,13 +3816,31 @@ QItemSelectionModel::SelectionFlags QAbstractItemView::selectionCommand(const QM const QEvent *event) const { Q_D(const QAbstractItemView); + Qt::KeyboardModifiers keyModifiers = Qt::NoModifier; + if (event) { + switch (event->type()) { + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + case QEvent::KeyPress: + case QEvent::KeyRelease: + keyModifiers = (static_cast<const QInputEvent*>(event))->modifiers(); + break; + default: + keyModifiers = QApplication::keyboardModifiers(); + } + } switch (d->selectionMode) { case NoSelection: // Never update selection model return QItemSelectionModel::NoUpdate; case SingleSelection: // ClearAndSelect on valid index otherwise NoUpdate if (event && event->type() == QEvent::MouseButtonRelease) return QItemSelectionModel::NoUpdate; - return QItemSelectionModel::ClearAndSelect|d->selectionBehaviorFlags(); + if ((keyModifiers & Qt::ControlModifier) && d->selectionModel->isSelected(index)) + return QItemSelectionModel::Deselect | d->selectionBehaviorFlags(); + else + return QItemSelectionModel::ClearAndSelect | d->selectionBehaviorFlags(); case MultiSelection: return d->multiSelectionCommand(index, event); case ExtendedSelection: diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index e0b1236679..c4ea213f29 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -9086,7 +9086,7 @@ QLayout *QWidget::layout() const existing layout manager (returned by layout()) before you can call setLayout() with the new layout. - If \a layout is the layout manger on a different widget, setLayout() + If \a layout is the layout manager on a different widget, setLayout() will reparent the layout and make it the layout manager for this widget. Example: diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp index bed3192219..a00637deb7 100644 --- a/src/widgets/styles/qstyleanimation.cpp +++ b/src/widgets/styles/qstyleanimation.cpp @@ -46,13 +46,9 @@ QT_BEGIN_NAMESPACE -QStyleAnimation::QStyleAnimation(QObject *target) : QAbstractAnimation(), +QStyleAnimation::QStyleAnimation(QObject *target) : QAbstractAnimation(target), _delay(0), _duration(-1), _startTime(QTime::currentTime()) { - if (target) { - moveToThread(target->thread()); - setParent(target); - } } QStyleAnimation::~QStyleAnimation() diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index 362f875629..63596a64af 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -1032,20 +1032,6 @@ void QLabel::paintEvent(QPaintEvent *) d->ensureTextLayouted(); QAbstractTextDocumentLayout::PaintContext context; - if (!isEnabled() && !d->control && - // We cannot support etched for rich text controls because custom - // colors and links will override the light palette - style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) { - context.palette = opt.palette; - context.palette.setColor(QPalette::Text, context.palette.light().color()); - painter.save(); - painter.translate(lr.x() + 1, lr.y() + 1); - painter.setClipRect(lr.translated(-lr.x() - 1, -lr.y() - 1)); - QAbstractTextDocumentLayout *layout = d->control->document()->documentLayout(); - layout->draw(&painter, context); - painter.restore(); - } - // Adjust the palette context.palette = opt.palette; |