summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/widgets/qmainwindow.cpp171
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp58
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h263
3 files changed, 254 insertions, 238 deletions
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 8eb5669f1c..e47efb50b3 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -73,9 +73,6 @@ public:
#ifdef Q_OS_OSX
, useUnifiedToolBar(false)
#endif
-#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
- , hasOldCursor(false) , cursorAdjusted(false)
-#endif
{ }
QMainWindowLayout *layout;
QSize iconSize;
@@ -85,17 +82,6 @@ public:
bool useUnifiedToolBar;
#endif
void init();
- QList<int> hoverSeparator;
- QPoint hoverPos;
-
-#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
- QCursor separatorCursor(const QList<int> &path) const;
- void adjustCursor(const QPoint &pos);
- QCursor oldCursor;
- QCursor adjustedCursor;
- uint hasOldCursor : 1;
- uint cursorAdjusted : 1;
-#endif
static inline QMainWindowLayout *mainWindowLayout(const QMainWindow *mainWindow)
{
@@ -1310,153 +1296,14 @@ bool QMainWindow::restoreState(const QByteArray &state, int version)
return restored;
}
-#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
-QCursor QMainWindowPrivate::separatorCursor(const QList<int> &path) const
-{
- QDockAreaLayoutInfo *info = layout->layoutState.dockAreaLayout.info(path);
- Q_ASSERT(info != 0);
- if (path.size() == 1) { // is this the "top-level" separator which separates a dock area
- // from the central widget?
- switch (path.first()) {
- case QInternal::LeftDock:
- case QInternal::RightDock:
- return Qt::SplitHCursor;
- case QInternal::TopDock:
- case QInternal::BottomDock:
- return Qt::SplitVCursor;
- default:
- break;
- }
- }
-
- // no, it's a splitter inside a dock area, separating two dock widgets
-
- return info->o == Qt::Horizontal
- ? Qt::SplitHCursor : Qt::SplitVCursor;
-}
-
-void QMainWindowPrivate::adjustCursor(const QPoint &pos)
-{
- Q_Q(QMainWindow);
-
- hoverPos = pos;
-
- if (pos == QPoint(0, 0)) {
- if (!hoverSeparator.isEmpty())
- q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
- hoverSeparator.clear();
-
- if (cursorAdjusted) {
- cursorAdjusted = false;
- if (hasOldCursor)
- q->setCursor(oldCursor);
- else
- q->unsetCursor();
- }
- } else if (layout->movingSeparator.isEmpty()) { // Don't change cursor when moving separator
- QList<int> pathToSeparator
- = layout->layoutState.dockAreaLayout.findSeparator(pos);
-
- if (pathToSeparator != hoverSeparator) {
- if (!hoverSeparator.isEmpty())
- q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
-
- hoverSeparator = pathToSeparator;
-
- if (hoverSeparator.isEmpty()) {
- if (cursorAdjusted) {
- cursorAdjusted = false;
- if (hasOldCursor)
- q->setCursor(oldCursor);
- else
- q->unsetCursor();
- }
- } else {
- q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
- if (!cursorAdjusted) {
- oldCursor = q->cursor();
- hasOldCursor = q->testAttribute(Qt::WA_SetCursor);
- }
- adjustedCursor = separatorCursor(hoverSeparator);
- q->setCursor(adjustedCursor);
- cursorAdjusted = true;
- }
- }
- }
-}
-#endif
-
/*! \reimp */
bool QMainWindow::event(QEvent *event)
{
Q_D(QMainWindow);
+ if (d->layout && d->layout->windowEvent(event))
+ return true;
switch (event->type()) {
-#ifndef QT_NO_DOCKWIDGET
- case QEvent::Paint: {
- QPainter p(this);
- QRegion r = static_cast<QPaintEvent*>(event)->region();
- d->layout->layoutState.dockAreaLayout.paintSeparators(&p, this, r, d->hoverPos);
- break;
- }
-
-#ifndef QT_NO_CURSOR
- case QEvent::HoverMove: {
- d->adjustCursor(static_cast<QHoverEvent*>(event)->pos());
- break;
- }
-
- // We don't want QWidget to call update() on the entire QMainWindow
- // on HoverEnter and HoverLeave, hence accept the event (return true).
- case QEvent::HoverEnter:
- return true;
- case QEvent::HoverLeave:
- d->adjustCursor(QPoint(0, 0));
- return true;
- case QEvent::ShortcutOverride: // when a menu pops up
- d->adjustCursor(QPoint(0, 0));
- break;
-#endif // QT_NO_CURSOR
-
- case QEvent::MouseButtonPress: {
- QMouseEvent *e = static_cast<QMouseEvent*>(event);
- if (e->button() == Qt::LeftButton && d->layout->startSeparatorMove(e->pos())) {
- // The click was on a separator, eat this event
- e->accept();
- return true;
- }
- break;
- }
-
- case QEvent::MouseMove: {
- QMouseEvent *e = static_cast<QMouseEvent*>(event);
-
-#ifndef QT_NO_CURSOR
- d->adjustCursor(e->pos());
-#endif
- if (e->buttons() & Qt::LeftButton) {
- if (d->layout->separatorMove(e->pos())) {
- // We're moving a separator, eat this event
- e->accept();
- return true;
- }
- }
-
- break;
- }
-
- case QEvent::MouseButtonRelease: {
- QMouseEvent *e = static_cast<QMouseEvent*>(event);
- if (d->layout->endSeparatorMove(e->pos())) {
- // We've released a separator, eat this event
- e->accept();
- return true;
- }
- break;
- }
-
-#endif
-
#ifndef QT_NO_TOOLBAR
case QEvent::ToolBarChange: {
d->layout->toggleToolBarsVisible();
@@ -1482,20 +1329,6 @@ bool QMainWindow::event(QEvent *event)
if (!d->explicitIconSize)
setIconSize(QSize());
break;
-#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
- case QEvent::CursorChange:
- // CursorChange events are triggered as mouse moves to new widgets even
- // if the cursor doesn't actually change, so do not change oldCursor if
- // the "changed" cursor has same shape as adjusted cursor.
- if (d->cursorAdjusted && d->adjustedCursor.shape() != cursor().shape()) {
- d->oldCursor = cursor();
- d->hasOldCursor = testAttribute(Qt::WA_SetCursor);
-
- // Ensure our adjusted cursor stays visible
- setCursor(d->adjustedCursor);
- }
- break;
-#endif
default:
break;
}
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 98421588a7..30217733cf 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -1689,39 +1689,6 @@ void QMainWindowLayout::tabMoved(int from, int to)
}
#endif // QT_NO_TABBAR
-bool QMainWindowLayout::startSeparatorMove(const QPoint &pos)
-{
- movingSeparator = layoutState.dockAreaLayout.findSeparator(pos);
-
- if (movingSeparator.isEmpty())
- return false;
-
- layoutState.dockAreaLayout.fallbackToSizeHints = false;
-
- savedState = layoutState;
- movingSeparatorPos = movingSeparatorOrigin = pos;
-
- return true;
-}
-
-bool QMainWindowLayout::separatorMove(const QPoint &pos)
-{
- if (movingSeparator.isEmpty())
- return false;
- movingSeparatorPos = pos;
- separatorMoveTimer.start(0, this);
- return true;
-}
-
-bool QMainWindowLayout::endSeparatorMove(const QPoint&)
-{
- if (movingSeparator.isEmpty())
- return false;
- movingSeparator.clear();
- savedState.clear();
- return true;
-}
-
void QMainWindowLayout::raise(QDockWidget *widget)
{
#ifndef QT_NO_TABBAR
@@ -2424,6 +2391,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
}
}
setCurrentHoveredFloat(nullptr);
+ layoutState.dockAreaLayout.fallbackToSizeHints = false;
#endif //QT_NO_DOCKWIDGET
QPoint pos = parentWidget()->mapFromGlobal(mousePos);
@@ -2575,30 +2543,6 @@ bool QMainWindowLayout::restoreState(QDataStream &stream)
return true;
}
-void QMainWindowLayout::timerEvent(QTimerEvent *e)
-{
-#ifndef QT_NO_DOCKWIDGET
- if (e->timerId() == separatorMoveTimer.timerId()) {
- //let's move the separators
- separatorMoveTimer.stop();
- if (movingSeparator.isEmpty())
- return;
- if (movingSeparatorOrigin == movingSeparatorPos)
- return;
-
- //when moving the separator, we need to update the previous position
- parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
-
- layoutState = savedState;
- layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
- movingSeparatorPos);
- movingSeparatorPos = movingSeparatorOrigin;
- }
-#endif
- QLayout::timerEvent(e);
-}
-
-
QT_END_NAMESPACE
#include "moc_qmainwindowlayout_p.cpp"
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index 507759fe96..dcd94e3617 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -58,6 +58,8 @@
#include "QtWidgets/qlayout.h"
#include "QtWidgets/qtabbar.h"
+#include "QtGui/qpainter.h"
+#include "QtGui/qevent.h"
#include "QtCore/qvector.h"
#include "QtCore/qset.h"
#include "QtCore/qbasictimer.h"
@@ -72,6 +74,251 @@ QT_BEGIN_NAMESPACE
class QToolBar;
class QRubberBand;
+template <typename Layout> // Make use of the "Curiously recurring template pattern"
+class QMainWindowLayoutSeparatorHelper
+{
+ Layout *layout() { return static_cast<Layout *>(this); }
+ const Layout *layout() const { return static_cast<const Layout *>(this); }
+ QWidget *window() { return layout()->parentWidget(); }
+
+public:
+ QList<int> hoverSeparator;
+ QPoint hoverPos;
+
+#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
+ QCursor separatorCursor(const QList<int> &path);
+ void adjustCursor(const QPoint &pos);
+ QCursor oldCursor;
+ QCursor adjustedCursor;
+ bool hasOldCursor = false;
+ bool cursorAdjusted = false;
+
+ QList<int> movingSeparator;
+ QPoint movingSeparatorOrigin, movingSeparatorPos;
+ QBasicTimer separatorMoveTimer;
+
+ bool startSeparatorMove(const QPoint &pos);
+ bool separatorMove(const QPoint &pos);
+ bool endSeparatorMove(const QPoint &pos);
+
+#endif
+
+ bool windowEvent(QEvent *e);
+};
+
+#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
+template <typename Layout>
+QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(const QList<int> &path)
+{
+ const QDockAreaLayoutInfo *info = layout()->dockAreaLayoutInfo()->info(path);
+ Q_ASSERT(info != 0);
+ if (path.size() == 1) { // is this the "top-level" separator which separates a dock area
+ // from the central widget?
+ switch (path.first()) {
+ case QInternal::LeftDock:
+ case QInternal::RightDock:
+ return Qt::SplitHCursor;
+ case QInternal::TopDock:
+ case QInternal::BottomDock:
+ return Qt::SplitVCursor;
+ default:
+ break;
+ }
+ }
+
+ // no, it's a splitter inside a dock area, separating two dock widgets
+
+ return info->o == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor;
+}
+
+template <typename Layout>
+void QMainWindowLayoutSeparatorHelper<Layout>::adjustCursor(const QPoint &pos)
+{
+ QWidget *w = layout()->window();
+ hoverPos = pos;
+
+ if (pos == QPoint(0, 0)) {
+ if (!hoverSeparator.isEmpty())
+ w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
+ hoverSeparator.clear();
+
+ if (cursorAdjusted) {
+ cursorAdjusted = false;
+ if (hasOldCursor)
+ w->setCursor(oldCursor);
+ else
+ w->unsetCursor();
+ }
+ } else if (movingSeparator.isEmpty()) { // Don't change cursor when moving separator
+ QList<int> pathToSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos);
+
+ if (pathToSeparator != hoverSeparator) {
+ if (!hoverSeparator.isEmpty())
+ w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
+
+ hoverSeparator = pathToSeparator;
+
+ if (hoverSeparator.isEmpty()) {
+ if (cursorAdjusted) {
+ cursorAdjusted = false;
+ if (hasOldCursor)
+ w->setCursor(oldCursor);
+ else
+ w->unsetCursor();
+ }
+ } else {
+ w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
+ if (!cursorAdjusted) {
+ oldCursor = w->cursor();
+ hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
+ }
+ adjustedCursor = separatorCursor(hoverSeparator);
+ w->setCursor(adjustedCursor);
+ cursorAdjusted = true;
+ }
+ }
+ }
+}
+
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
+{
+ QWidget *w = window();
+ switch (event->type()) {
+ case QEvent::Paint: {
+ QPainter p(w);
+ QRegion r = static_cast<QPaintEvent *>(event)->region();
+ layout()->dockAreaLayoutInfo()->paintSeparators(&p, w, r, hoverPos);
+ break;
+ }
+
+#ifndef QT_NO_CURSOR
+ case QEvent::HoverMove: {
+ adjustCursor(static_cast<QHoverEvent *>(event)->pos());
+ break;
+ }
+
+ // We don't want QWidget to call update() on the entire QMainWindow
+ // on HoverEnter and HoverLeave, hence accept the event (return true).
+ case QEvent::HoverEnter:
+ return true;
+ case QEvent::HoverLeave:
+ adjustCursor(QPoint(0, 0));
+ return true;
+ case QEvent::ShortcutOverride: // when a menu pops up
+ adjustCursor(QPoint(0, 0));
+ break;
+#endif // QT_NO_CURSOR
+
+ case QEvent::MouseButtonPress: {
+ QMouseEvent *e = static_cast<QMouseEvent *>(event);
+ if (e->button() == Qt::LeftButton && startSeparatorMove(e->pos())) {
+ // The click was on a separator, eat this event
+ e->accept();
+ return true;
+ }
+ break;
+ }
+
+ case QEvent::MouseMove: {
+ QMouseEvent *e = static_cast<QMouseEvent *>(event);
+
+#ifndef QT_NO_CURSOR
+ adjustCursor(e->pos());
+#endif
+ if (e->buttons() & Qt::LeftButton) {
+ if (separatorMove(e->pos())) {
+ // We're moving a separator, eat this event
+ e->accept();
+ return true;
+ }
+ }
+
+ break;
+ }
+
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent *e = static_cast<QMouseEvent *>(event);
+ if (endSeparatorMove(e->pos())) {
+ // We've released a separator, eat this event
+ e->accept();
+ return true;
+ }
+ break;
+ }
+
+#if !defined(QT_NO_CURSOR)
+ case QEvent::CursorChange:
+ // CursorChange events are triggered as mouse moves to new widgets even
+ // if the cursor doesn't actually change, so do not change oldCursor if
+ // the "changed" cursor has same shape as adjusted cursor.
+ if (cursorAdjusted && adjustedCursor.shape() != w->cursor().shape()) {
+ oldCursor = w->cursor();
+ hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
+
+ // Ensure our adjusted cursor stays visible
+ w->setCursor(adjustedCursor);
+ }
+ break;
+#endif
+ case QEvent::Timer:
+ if (static_cast<QTimerEvent *>(event)->timerId() == separatorMoveTimer.timerId()) {
+ // let's move the separators
+ separatorMoveTimer.stop();
+ if (movingSeparator.isEmpty())
+ return true;
+ if (movingSeparatorOrigin == movingSeparatorPos)
+ return true;
+
+ // when moving the separator, we need to update the previous position
+ window()->update(layout()->dockAreaLayoutInfo()->separatorRegion());
+
+ layout()->layoutState = layout()->savedState;
+ layout()->dockAreaLayoutInfo()->separatorMove(movingSeparator, movingSeparatorOrigin,
+ movingSeparatorPos);
+ movingSeparatorPos = movingSeparatorOrigin;
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::startSeparatorMove(const QPoint &pos)
+{
+ movingSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos);
+
+ if (movingSeparator.isEmpty())
+ return false;
+
+ layout()->savedState = layout()->layoutState;
+ movingSeparatorPos = movingSeparatorOrigin = pos;
+
+ return true;
+}
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::separatorMove(const QPoint &pos)
+{
+ if (movingSeparator.isEmpty())
+ return false;
+ movingSeparatorPos = pos;
+ separatorMoveTimer.start(0, window());
+ return true;
+}
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::endSeparatorMove(const QPoint &)
+{
+ if (movingSeparator.isEmpty())
+ return false;
+ movingSeparator.clear();
+ layout()->savedState.clear();
+ return true;
+}
+#endif
+
#ifndef QT_NO_DOCKWIDGET
class QDockWidgetGroupWindow : public QWidget
{
@@ -168,7 +415,9 @@ public:
bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState);
};
-class Q_AUTOTEST_EXPORT QMainWindowLayout : public QLayout
+class Q_AUTOTEST_EXPORT QMainWindowLayout
+ : public QLayout,
+ public QMainWindowLayoutSeparatorHelper<QMainWindowLayout>
{
Q_OBJECT
@@ -181,8 +430,6 @@ public:
QMainWindow::DockOptions dockOptions;
void setDockOptions(QMainWindow::DockOptions opts);
- void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
-
// status bar
QLayoutItem *statusbar;
@@ -260,15 +507,7 @@ public:
#endif // QT_NO_TABWIDGET
#endif // QT_NO_TABBAR
- // separators
-
- QList<int> movingSeparator;
- QPoint movingSeparatorOrigin, movingSeparatorPos;
- QBasicTimer separatorMoveTimer;
-
- bool startSeparatorMove(const QPoint &pos);
- bool separatorMove(const QPoint &pos);
- bool endSeparatorMove(const QPoint &pos);
+ QDockAreaLayout *dockAreaLayoutInfo() { return &layoutState.dockAreaLayout; }
void keepSize(QDockWidget *w);
#endif // QT_NO_DOCKWIDGET