summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp24
-rw-r--r--src/widgets/dialogs/qmessagebox.h4
-rw-r--r--src/widgets/dialogs/qwizard.cpp6
-rw-r--r--src/widgets/dialogs/qwizard_win.cpp88
-rw-r--r--src/widgets/dialogs/qwizard_win_p.h10
-rw-r--r--src/widgets/doc/qtwidgets.qdocconf10
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp73
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp100
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h1
-rw-r--r--src/widgets/graphicsview/qgraphicsscene_p.h3
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.cpp104
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp20
-rw-r--r--src/widgets/kernel/qwidget.cpp2
-rw-r--r--src/widgets/styles/qstyleanimation.cpp6
-rw-r--r--src/widgets/widgets/qlabel.cpp14
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> &region);
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;