diff options
Diffstat (limited to 'src/widgets/widgets')
37 files changed, 911 insertions, 887 deletions
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index e0bc198d2e..1338a496e6 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -45,6 +45,7 @@ #include <qlineedit.h> #include <qapplication.h> #include <qdesktopwidget.h> +#include <private/qdesktopwidget_p.h> #include <qlistview.h> #if QT_CONFIG(tableview) #include <qtableview.h> @@ -73,11 +74,6 @@ #include <private/qlineedit_p.h> #include <private/qcompleter_p.h> #include <qdebug.h> -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(effetcts) && QT_CONFIG(style_mac) -#include <private/qcore_mac_p.h> -#include <private/qmacstyle_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#endif #if QT_CONFIG(effects) # include <private/qeffects_p.h> #endif @@ -203,7 +199,21 @@ void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index) if (index.isValid() && q->completer()) { QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(q->completer()->completionModel()); if (proxy) { - q->setCurrentIndex(proxy->mapToSource(index).row()); + const QModelIndex &completerIndex = proxy->mapToSource(index); + int row = -1; + if (completerIndex.model() == model) { + row = completerIndex.row(); + } else { + // if QCompleter uses a proxy model to host widget's one - map again + QAbstractProxyModel *completerProxy = qobject_cast<QAbstractProxyModel *>(q->completer()->model()); + if (completerProxy && completerProxy->sourceModel() == model) { + row = completerProxy->mapToSource(completerIndex).row(); + } else { + QString match = q->completer()->model()->data(completerIndex).toString(); + row = q->findText(match, matchFlags()); + } + } + q->setCurrentIndex(row); emitActivated(currentIndex); } } @@ -256,8 +266,8 @@ QRect QComboBoxPrivate::popupGeometry(int screen) const if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) useFullScreenForPopupMenu = theme->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool(); return useFullScreenForPopupMenu ? - QApplication::desktop()->screenGeometry(screen) : - QApplication::desktop()->availableGeometry(screen); + QDesktopWidgetPrivate::screenGeometry(screen) : + QDesktopWidgetPrivate::availableGeometry(screen); } bool QComboBoxPrivate::updateHoverControl(const QPoint &pos) @@ -487,6 +497,14 @@ void QComboBoxPrivateContainer::scrollItemView(int action) #endif } +void QComboBoxPrivateContainer::hideScrollers() +{ + if (top) + top->hide(); + if (bottom) + bottom->hide(); +} + /* Hides or shows the scrollers when we emulate a popupmenu */ @@ -2612,7 +2630,7 @@ void QComboBox::showPopup() QComboBoxPrivateContainer* container = d->viewContainer(); QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); - QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(this)); + QRect screen = d->popupGeometry(QDesktopWidgetPrivate::screenNumber(this)); QPoint below = mapToGlobal(listRect.bottomLeft()); int belowHeight = screen.bottom() - below.y(); @@ -2747,6 +2765,11 @@ void QComboBox::showPopup() if (needHorizontalScrollBar) { listRect.adjust(0, 0, 0, sb->height()); } + + // Hide the scrollers here, so that the listrect gets the full height of the container + // If the scrollers are truly needed, the later call to container->updateScrollers() + // will make them visible again. + container->hideScrollers(); container->setGeometry(listRect); #ifndef Q_OS_MAC diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index 249610825a..835bbf866e 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -215,7 +215,7 @@ private: bool fast; }; -class Q_AUTOTEST_EXPORT QComboBoxPrivateContainer : public QFrame +class Q_WIDGETS_EXPORT QComboBoxPrivateContainer : public QFrame { Q_OBJECT @@ -234,6 +234,7 @@ public: public Q_SLOTS: void scrollItemView(int action); + void hideScrollers(); void updateScrollers(); void viewDestroyed(); diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index 053b184226..b6ec6b4065 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -42,6 +42,7 @@ #include <qapplication.h> #include <qdatetimeedit.h> #include <qdesktopwidget.h> +#include <private/qdesktopwidget_p.h> #include <qdebug.h> #include <qevent.h> #include <qlineedit.h> @@ -1073,7 +1074,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) //hide cursor d->edit->d_func()->setCursorVisible(false); - d->edit->d_func()->control->setCursorBlinkPeriod(0); + d->edit->d_func()->control->setBlinkingCursorEnabled(false); d->setSelected(0); } } @@ -1094,7 +1095,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event) //hide cursor d->edit->d_func()->setCursorVisible(false); - d->edit->d_func()->control->setCursorBlinkPeriod(0); + d->edit->d_func()->control->setBlinkingCursorEnabled(false); d->setSelected(0); oldCurrent = 0; } @@ -1921,6 +1922,7 @@ QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &positi } StateNode tmp = parse(input, position, value.toDateTime(), fixup); input = tmp.input; + position += tmp.padded; state = QValidator::State(int(tmp.state)); if (state == QValidator::Acceptable) { if (tmp.conflicts && conflictGuard != tmp.value) { @@ -2515,7 +2517,7 @@ void QDateTimeEditPrivate::positionCalendarPopup() pos = q->mapToGlobal(pos); pos2 = q->mapToGlobal(pos2); QSize size = monthCalendar->sizeHint(); - QRect screen = QApplication::desktop()->availableGeometry(pos); + QRect screen = QDesktopWidgetPrivate::availableGeometry(pos); //handle popup falling "off screen" if (q->layoutDirection() == Qt::RightToLeft) { pos.setX(pos.x()-size.width()); diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp index 90cb17da59..788ec67fb2 100644 --- a/src/widgets/widgets/qdialogbuttonbox.cpp +++ b/src/widgets/widgets/qdialogbuttonbox.cpp @@ -579,6 +579,8 @@ QDialogButtonBox::~QDialogButtonBox() \value MacLayout Use a policy appropriate for applications on \macos. \value KdeLayout Use a policy appropriate for applications on KDE. \value GnomeLayout Use a policy appropriate for applications on GNOME. + \value AndroidLayout Use a policy appropriate for applications on Android. + This enum value was added in Qt 5.10. The button layout is specified by the \l{style()}{current style}. However, on the X11 platform, it may be influenced by the desktop environment. diff --git a/src/widgets/widgets/qdialogbuttonbox.h b/src/widgets/widgets/qdialogbuttonbox.h index af9e705234..02d14dee7c 100644 --- a/src/widgets/widgets/qdialogbuttonbox.h +++ b/src/widgets/widgets/qdialogbuttonbox.h @@ -108,11 +108,13 @@ public: Q_FLAG(StandardButtons) enum ButtonLayout { - // keep this in sync with QMessageBox::ButtonLayout and QPlatformDialogHelper::ButtonLayout + // keep this in sync with QPlatformDialogHelper::ButtonLayout WinLayout, MacLayout, KdeLayout, - GnomeLayout + GnomeLayout, + // MacModelessLayout, + AndroidLayout = GnomeLayout + 2 // ### Qt 6: reorder }; QDialogButtonBox(QWidget *parent = Q_NULLPTR); diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 21d1d4cb85..71726eaeee 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -45,6 +45,7 @@ #endif #include "QtWidgets/qstyle.h" #include "QtWidgets/qdesktopwidget.h" +#include <private/qdesktopwidget_p.h> #include "QtWidgets/qapplication.h" #include "QtCore/qvariant.h" #include "qdockarealayout_p.h" @@ -1044,33 +1045,6 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path) Q_ASSERT(item.widgetItem != 0); Q_ASSERT(item.flags & QDockAreaLayoutItem::GapItem); item.flags &= ~QDockAreaLayoutItem::GapItem; - - QRect result; - -#if QT_CONFIG(tabbar) - if (tabbed) { - } else -#endif - { - int prev = this->prev(index); - int next = this->next(index); - - if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { - item.pos += *sep; - item.size -= *sep; - } - if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - item.size -= *sep; - - QPoint pos; - rpick(o, pos) = item.pos; - rperp(o, pos) = perp(o, rect.topLeft()); - QSize s; - rpick(o, s) = item.size; - rperp(o, s) = perp(o, rect.size()); - result = QRect(pos, s); - } - return item.widgetItem; } @@ -1323,29 +1297,46 @@ QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(const QList<int> &path) return item_list[index].subinfo->info(path.mid(1)); } -QRect QDockAreaLayoutInfo::itemRect(int index) const +QRect QDockAreaLayoutInfo::itemRect(int index, bool isGap) const { const QDockAreaLayoutItem &item = item_list.at(index); if (item.skip()) return QRect(); + if (isGap && !(item.flags & QDockAreaLayoutItem::GapItem)) + return QRect(); + QRect result; #if QT_CONFIG(tabbar) if (tabbed) { - if (tabId(item) == currentTabId()) + if (isGap || tabId(item) == currentTabId()) result = tabContentRect(); } else #endif { - QPoint pos; - rpick(o, pos) = item.pos; - rperp(o, pos) = perp(o, rect.topLeft()); + int pos = item.pos; + int size = item.size; + + if (isGap) { + int prev = this->prev(index); + int next = this->next(index); + if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { + pos += *sep; + size -= *sep; + } + if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) + size -= *sep; + } + + QPoint p; + rpick(o, p) = pos; + rperp(o, p) = perp(o, rect.topLeft()); QSize s; - rpick(o, s) = item.size; + rpick(o, s) = size; rperp(o, s) = perp(o, rect.size()); - result = QRect(pos, s); + result = QRect(p, s); } return result; @@ -2426,20 +2417,21 @@ QList<int> QDockAreaLayout::indexOf(QWidget *dockWidget) const return QList<int>(); } -QList<int> QDockAreaLayout::gapIndex(const QPoint &pos) const +QList<int> QDockAreaLayout::gapIndex(const QPoint &pos, bool disallowTabs) const { QMainWindow::DockOptions opts = mainWindow->dockOptions(); bool nestingEnabled = opts & QMainWindow::AllowNestedDocks; QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs; #if QT_CONFIG(tabbar) - if (opts & QMainWindow::AllowTabbedDocks - || opts & QMainWindow::VerticalTabs) - tabMode = QDockAreaLayoutInfo::AllowTabs; - if (opts & QMainWindow::ForceTabbedDocks) - tabMode = QDockAreaLayoutInfo::ForceTabs; + if (!disallowTabs) { + if (opts & QMainWindow::AllowTabbedDocks || opts & QMainWindow::VerticalTabs) + tabMode = QDockAreaLayoutInfo::AllowTabs; + if (opts & QMainWindow::ForceTabbedDocks) + tabMode = QDockAreaLayoutInfo::ForceTabs; - if (tabMode == QDockAreaLayoutInfo::ForceTabs) - nestingEnabled = false; + if (tabMode == QDockAreaLayoutInfo::ForceTabs) + nestingEnabled = false; + } #endif @@ -3052,11 +3044,10 @@ QSize QDockAreaLayout::minimumSize() const QRect QDockAreaLayout::constrainedRect(QRect rect, QWidget* widget) { QRect desktop; - QDesktopWidget *desktopW = QApplication::desktop(); - if (desktopW->isVirtualDesktop()) - desktop = desktopW->screenGeometry(rect.topLeft()); + if (QDesktopWidgetPrivate::isVirtualDesktop()) + desktop = QDesktopWidgetPrivate::screenGeometry(rect.topLeft()); else - desktop = desktopW->screenGeometry(widget); + desktop = QDesktopWidgetPrivate::screenGeometry(widget); if (desktop.isValid()) { rect.setWidth(qMin(rect.width(), desktop.width())); @@ -3311,6 +3302,19 @@ int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &or return delta; } +int QDockAreaLayoutInfo::separatorMove(const QList<int> &separator, const QPoint &origin, + const QPoint &dest) +{ + int delta = 0; + int index = separator.last(); + QDockAreaLayoutInfo *info = this->info(separator); + delta = pick(info->o, dest - origin); + if (delta != 0) + delta = info->separatorMove(index, delta); + info->apply(false); + return delta; +} + #if QT_CONFIG(tabbar) // Sets the correct positions for the separator widgets // Allocates new sepearator widgets with getSeparatorWidget @@ -3420,47 +3424,10 @@ QRect QDockAreaLayout::gapRect(const QList<int> &path) const const QDockAreaLayoutInfo *info = this->info(path); if (info == 0) return QRect(); - const QList<QDockAreaLayoutItem> &item_list = info->item_list; - Qt::Orientation o = info->o; int index = path.last(); - if (index < 0 || index >= item_list.count()) - return QRect(); - const QDockAreaLayoutItem &item = item_list.at(index); - if (!(item.flags & QDockAreaLayoutItem::GapItem)) + if (index < 0 || index >= info->item_list.count()) return QRect(); - - QRect result; - -#if QT_CONFIG(tabbar) - if (info->tabbed) { - result = info->tabContentRect(); - } else -#endif - { - int pos = item.pos; - int size = item.size; - - int prev = info->prev(index); - int next = info->next(index); - - if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) { - pos += sep; - size -= sep; - } - if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem)) - size -= sep; - - QPoint p; - rpick(o, p) = pos; - rperp(o, p) = perp(o, info->rect.topLeft()); - QSize s; - rpick(o, s) = size; - rperp(o, s) = perp(o, info->rect.size()); - - result = QRect(p, s); - } - - return result; + return info->itemRect(index, true); } void QDockAreaLayout::keepSize(QDockWidget *w) diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h index 82244c192e..49bd157179 100644 --- a/src/widgets/widgets/qdockarealayout_p.h +++ b/src/widgets/widgets/qdockarealayout_p.h @@ -160,7 +160,7 @@ public: void fitItems(); bool expansive(Qt::Orientation o) const; int changeSize(int index, int size, bool below); - QRect itemRect(int index) const; + QRect itemRect(int index, bool isGap = false) const; QRect itemRect(const QList<int> &path) const; QRect separatorRect(int index) const; QRect separatorRect(const QList<int> &path) const; @@ -182,6 +182,7 @@ public: const QPoint &mouse) const; QRegion separatorRegion() const; int separatorMove(int index, int delta); + int separatorMove(const QList<int> &separator, const QPoint &origin, const QPoint &dest); QLayoutItem *itemAt(int *x, int index) const; QLayoutItem *takeAt(int *x, int index); @@ -246,7 +247,7 @@ public: QList<int> indexOfPlaceHolder(const QString &objectName) const; QList<int> indexOf(QWidget *dockWidget) const; - QList<int> gapIndex(const QPoint &pos) const; + QList<int> gapIndex(const QPoint &pos, bool disallowTabs) const; QList<int> findSeparator(const QPoint &pos) const; QDockAreaLayoutItem &item(const QList<int> &path); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 8d7d2a82d5..bfb3a98d7e 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -56,11 +56,6 @@ #include "qdockwidget_p.h" #include "qmainwindowlayout_p.h" -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include <private/qapplication_p.h> -#include <private/qt_mac_p.h> -#include <private/qmacstyle_mac_p.h> -#endif QT_BEGIN_NAMESPACE @@ -217,10 +212,9 @@ QDockWidgetLayout::~QDockWidgetLayout() bool QDockWidgetLayout::nativeWindowDeco() const { bool floating = parentWidget()->isWindow(); - if (!floating) { - if (auto groupWindow = qobject_cast<const QDockWidgetGroupWindow*>(parentWidget()->parentWidget())) - return groupWindow->hasNativeDecos(); - } + if (auto groupWindow = + qobject_cast<const QDockWidgetGroupWindow *>(parentWidget()->parentWidget())) + floating = floating || groupWindow->tabLayoutInfo(); return nativeWindowDeco(floating); } @@ -1442,7 +1436,7 @@ void QDockWidget::paintEvent(QPaintEvent *event) } // Title must be painted after the frame, since the areas overlap, and - // the title may wish to extend out to all sides (eg. XP style) + // the title may wish to extend out to all sides (eg. Vista style) QStyleOptionDockWidget titleOpt; initStyleOption(&titleOpt); p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt); diff --git a/src/widgets/widgets/qeffects.cpp b/src/widgets/widgets/qeffects.cpp index 437cee93df..d4ef33966b 100644 --- a/src/widgets/widgets/qeffects.cpp +++ b/src/widgets/widgets/qeffects.cpp @@ -50,6 +50,8 @@ #include "qelapsedtimer.h" #include "qdebug.h" +#include <private/qdesktopwidget_p.h> + QT_BEGIN_NAMESPACE /* @@ -97,7 +99,7 @@ static QAlphaWidget* q_blend = 0; Constructs a QAlphaWidget. */ QAlphaWidget::QAlphaWidget(QWidget* w, Qt::WindowFlags f) - : QWidget(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(w)), f) + : QWidget(QApplication::desktop()->screen(QDesktopWidgetPrivate::screenNumber(w)), f) { #ifndef Q_OS_WIN setEnabled(false); diff --git a/src/widgets/widgets/qfontcombobox.cpp b/src/widgets/widgets/qfontcombobox.cpp index f206d01999..1c56c19c8f 100644 --- a/src/widgets/widgets/qfontcombobox.cpp +++ b/src/widgets/widgets/qfontcombobox.cpp @@ -47,6 +47,7 @@ #include <qapplication.h> #include <private/qcombobox_p.h> #include <QDesktopWidget> +#include <private/qdesktopwidget_p.h> #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -540,7 +541,7 @@ bool QFontComboBox::event(QEvent *e) QListView *lview = qobject_cast<QListView*>(view()); if (lview) { lview->window()->setFixedWidth(qMin(width() * 5 / 3, - QApplication::desktop()->availableGeometry(lview).width())); + QDesktopWidgetPrivate::availableGeometry(lview).width())); } } return QComboBox::event(e); diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 13b204e825..d0a794222e 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -80,7 +80,10 @@ #include "private/qapplication_p.h" #include "private/qshortcutmap_p.h" #include "qkeysequence.h" -#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ +#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \ + ? false \ + : qApp->styleHints()->showShortcutsInContextMenus()) \ + && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString()) #else #define ACCEL_KEY(k) QString() @@ -93,10 +96,6 @@ QT_BEGIN_NAMESPACE -#if 0 // Used to be included in Qt4 for Q_WS_MAC -extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp -#endif - /*! Initialize \a option with the values from this QLineEdit. This method is useful for subclasses when they need a QStyleOptionFrame, but don't want @@ -578,10 +577,6 @@ void QLineEdit::setEchoMode(EchoMode mode) setInputMethodHints(imHints); d->control->setEchoMode(mode); update(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (hasFocus()) - qt_mac_secure_keyboard(mode == Password || mode == NoEcho); -#endif } @@ -964,6 +959,8 @@ QString QLineEdit::selectedText() const line edit or -1 if no text is selected. \sa selectedText() + \sa selectionEnd() + \sa selectionLength() */ int QLineEdit::selectionStart() const @@ -972,8 +969,33 @@ int QLineEdit::selectionStart() const return d->control->selectionStart(); } +/*! + Returns the index of the character directly after the selection + in the line edit or -1 if no text is selected. + \since 5.10 + + \sa selectedText() + \sa selectionStart() + \sa selectionLength() +*/ +int QLineEdit::selectionEnd() const +{ + Q_D(const QLineEdit); + return d->control->selectionEnd(); +} +/*! + Returns the length of the selection. + \since 5.10 + \sa selectedText() + \sa selectionStart() + \sa selectionEnd() +*/ +int QLineEdit::selectionLength() const +{ + return selectionEnd() - selectionStart(); +} /*! Selects text from position \a start and for \a length characters. @@ -1563,7 +1585,7 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e) d->control->copy(QClipboard::Selection); } else if (!d->control->isReadOnly() && e->button() == Qt::MidButton) { deselect(); - insert(QApplication::clipboard()->text(QClipboard::Selection)); + d->control->paste(QClipboard::Selection); } } #endif @@ -1818,10 +1840,6 @@ void QLineEdit::focusInEvent(QFocusEvent *e) if((!hasSelectedText() && d->control->preeditAreaText().isEmpty()) || style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this)) d->setCursorVisible(true); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) - qt_mac_secure_keyboard(true); -#endif #ifdef QT_KEYPAD_NAVIGATION d->control->setCancelText(d->control->text()); } @@ -1866,10 +1884,6 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) if (hasAcceptableInput() || d->control->fixup()) emit editingFinished(); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho) - qt_mac_secure_keyboard(false); -#endif #ifdef QT_KEYPAD_NAVIGATION d->control->setCancelText(QString()); #endif diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h index 08dd6f3b83..b98307390c 100644 --- a/src/widgets/widgets/qlineedit.h +++ b/src/widgets/widgets/qlineedit.h @@ -154,6 +154,8 @@ public: bool hasSelectedText() const; QString selectedText() const; int selectionStart() const; + int selectionEnd() const; + int selectionLength() const; bool isUndoAvailable() const; bool isRedoAvailable() const; diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 5c6f983149..d97fedadab 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -66,13 +66,6 @@ #ifdef Q_OS_OSX #include <qpa/qplatformnativeinterface.h> #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include <private/qt_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -QT_BEGIN_NAMESPACE -extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp -QT_END_NAMESPACE -#endif QT_BEGIN_NAMESPACE @@ -85,13 +78,6 @@ public: #ifdef Q_OS_OSX , useUnifiedToolBar(false) #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - , useHIToolBar(false) - , activateUnifiedToolbarAfterFullScreen(false) -#endif -#if QT_CONFIG(dockwidget) && !defined(QT_NO_CURSOR) - , hasOldCursor(false) , cursorAdjusted(false) -#endif { } QMainWindowLayout *layout; QSize iconSize; @@ -100,22 +86,7 @@ public: #ifdef Q_OS_OSX bool useUnifiedToolBar; #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - bool useHIToolBar; - bool activateUnifiedToolbarAfterFullScreen; -#endif void init(); - QList<int> hoverSeparator; - QPoint hoverPos; - -#if QT_CONFIG(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) { @@ -810,11 +781,7 @@ void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar) #endif } - if (!d->layout->usesHIToolBar(toolbar)) { - d->layout->removeWidget(toolbar); - } else { - d->layout->removeToolBar(toolbar); - } + d->layout->removeToolBar(toolbar); toolbar->d_func()->_q_updateIconSize(d->iconSize); toolbar->d_func()->_q_updateToolButtonStyle(d->toolButtonStyle); @@ -1116,21 +1083,6 @@ void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget } d_func()->layout->removeWidget(dockwidget); // in case it was already in here addDockWidget(area, dockwidget, orientation); - -#if 0 // Used to be included in Qt4 for Q_WS_MAC //drawer support - QMacAutoReleasePool pool; - extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp - if (qt_mac_is_macdrawer(dockwidget)) { - extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp - window()->createWinId(); - dockwidget->window()->createWinId(); - qt_mac_set_drawer_preferred_edge(dockwidget, area); - if (dockwidget->isVisible()) { - dockwidget->hide(); - dockwidget->show(); - } - } -#endif } /*! @@ -1349,153 +1301,14 @@ bool QMainWindow::restoreState(const QByteArray &state, int version) return restored; } -#if QT_CONFIG(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()) { -#if QT_CONFIG(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(); @@ -1521,40 +1334,6 @@ bool QMainWindow::event(QEvent *event) if (!d->explicitIconSize) setIconSize(QSize()); break; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - case QEvent::Show: - if (unifiedTitleAndToolBarOnMac()) - d->layout->syncUnifiedToolbarVisibility(); - d->layout->blockVisiblityCheck = false; - break; - case QEvent::WindowStateChange: - { - if (isHidden()) { - // We are coming out of a minimize, leave things as is. - d->layout->blockVisiblityCheck = true; - } - // We need to update the HIToolbar status when we go out of or into fullscreen. - QWindowStateChangeEvent *wce = static_cast<QWindowStateChangeEvent *>(event); - if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) { - d->layout->updateHIToolBarStatus(); - } - } - break; -#endif -#if QT_CONFIG(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; } @@ -1594,33 +1373,6 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) (reinterpret_cast<SetContentBorderEnabledFunction>(function))(window()->windowHandle(), set); update(); } -#endif - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - Q_D(QMainWindow); - if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3) - return; - - d->useHIToolBar = set; - createWinId(); // We need the hiview for down below. - - // Activate the unified toolbar with the raster engine. - if (windowSurface() && set) { - d->layout->unifiedSurface = new QUnifiedToolbarSurface(this); - } - - d->layout->updateHIToolBarStatus(); - - // Deactivate the unified toolbar with the raster engine. - if (windowSurface() && !set) { - if (d->layout->unifiedSurface) { - delete d->layout->unifiedSurface; - d->layout->unifiedSurface = 0; - } - } - - // Enabling the unified toolbar clears the opaque size grip setting, update it. - d->macUpdateOpaqueSizeGrip(); #else Q_UNUSED(set) #endif @@ -1631,9 +1383,6 @@ bool QMainWindow::unifiedTitleAndToolBarOnMac() const #ifdef Q_OS_OSX return d_func()->useUnifiedToolBar; #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - return d_func()->useHIToolBar && !testAttribute(Qt::WA_MacBrushedMetal) && !(windowFlags() & Qt::FramelessWindowHint); -#endif return false; } diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 91c012d8d8..1767a8458f 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -77,10 +77,6 @@ #include <private/qapplication_p.h> #include <private/qlayoutengine_p.h> #include <private/qwidgetresizehandler_p.h> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qcore_mac_p.h> -# include <private/qt_cocoa_helpers_mac_p.h> -#endif QT_BEGIN_NAMESPACE @@ -184,13 +180,17 @@ QDebug operator<<(QDebug debug, const QMainWindowLayout *layout) /****************************************************************************** ** QDockWidgetGroupWindow */ -// QDockWidgetGroupWindow is the floating window containing the tabbed dockwidgets in case several -// dockwidgets are dragged together (QMainWindow::GroupedDragging feature). +// QDockWidgetGroupWindow is the floating window containing several QDockWidgets floating together. +// (QMainWindow::GroupedDragging feature) // QDockWidgetGroupLayout is the layout of that window and use a QDockAreaLayoutInfo to layout -// the tabs inside it. +// the QDockWidgets inside it. +// If there is only one QDockWidgets, or all QDockWidgets are tabbed together, it is equivalent +// of a floating QDockWidget (the title of the QDockWidget is the title of the window). But if there +// are nested QDockWidget, an additional title bar is there. #if QT_CONFIG(dockwidget) -class QDockWidgetGroupLayout : public QLayout { - QDockAreaLayoutInfo info; +class QDockWidgetGroupLayout : public QLayout, + public QMainWindowLayoutSeparatorHelper<QDockWidgetGroupLayout> +{ QWidgetResizeHandler *resizer; public: QDockWidgetGroupLayout(QDockWidgetGroupWindow* parent) : QLayout(parent) { @@ -199,7 +199,7 @@ public: resizer->setMovingEnabled(false); } ~QDockWidgetGroupLayout() { - info.deleteAllLayoutItems(); + layoutState.deleteAllLayoutItems(); } void addItem(QLayoutItem*) Q_DECL_OVERRIDE { Q_UNREACHABLE(); } @@ -207,32 +207,43 @@ public: QLayoutItem* itemAt(int index) const Q_DECL_OVERRIDE { int x = 0; - return info.itemAt(&x, index); + return layoutState.itemAt(&x, index); } QLayoutItem* takeAt(int index) Q_DECL_OVERRIDE { int x = 0; - return info.takeAt(&x, index); + QLayoutItem *ret = layoutState.takeAt(&x, index); + if (savedState.rect.isValid() && ret->widget()) { + // we need to remove the item also from the saved state to prevent crash + QList<int> path = savedState.indexOf(ret->widget()); + if (!path.isEmpty()) + savedState.remove(path); + // Also, the item may be contained several times as a gap item. + path = layoutState.indexOf(ret->widget()); + if (!path.isEmpty()) + layoutState.remove(path); + } + return ret; } QSize sizeHint() const Q_DECL_OVERRIDE { int fw = frameWidth(); - return info.sizeHint() + QSize(fw, fw); + return layoutState.sizeHint() + QSize(fw, fw); } QSize minimumSize() const Q_DECL_OVERRIDE { int fw = frameWidth(); - return info.minimumSize() + QSize(fw, fw); + return layoutState.minimumSize() + QSize(fw, fw); } QSize maximumSize() const Q_DECL_OVERRIDE { int fw = frameWidth(); - return info.maximumSize() + QSize(fw, fw); + return layoutState.maximumSize() + QSize(fw, fw); } void setGeometry(const QRect&r) Q_DECL_OVERRIDE { groupWindow()->destroyOrHideIfEmpty(); - QDockAreaLayoutInfo *li = layoutInfo(); + QDockAreaLayoutInfo *li = dockAreaLayoutInfo(); if (li->isEmpty()) return; int fw = frameWidth(); @@ -242,12 +253,12 @@ public: li->rect = r.adjusted(fw, fw, -fw, -fw); li->fitItems(); li->apply(false); + if (savedState.rect.isValid()) + savedState.rect = li->rect; resizer->setActive(QWidgetResizeHandler::Resize, !nativeWindowDeco()); } - QDockAreaLayoutInfo *layoutInfo() { - return &info; - } + QDockAreaLayoutInfo *dockAreaLayoutInfo() { return &layoutState; } bool nativeWindowDeco() const { @@ -264,14 +275,21 @@ public: { return static_cast<QDockWidgetGroupWindow *>(parent()); } + + QDockAreaLayoutInfo layoutState; + QDockAreaLayoutInfo savedState; }; bool QDockWidgetGroupWindow::event(QEvent *e) { + auto lay = static_cast<QDockWidgetGroupLayout *>(layout()); + if (lay && lay->windowEvent(e)) + return true; + switch (e->type()) { case QEvent::Close: // Forward the close to the QDockWidget just as if its close button was pressed - if (QDockWidget *dw = topDockWidget()) { + if (QDockWidget *dw = activeTabbedDockWidget()) { e->ignore(); dw->close(); adjustFlags(); @@ -279,7 +297,7 @@ bool QDockWidgetGroupWindow::event(QEvent *e) return true; case QEvent::Move: // Let QDockWidgetPrivate::moseEvent handle the dragging - if (QDockWidget *dw = topDockWidget()) + if (QDockWidget *dw = activeTabbedDockWidget()) static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->moveEvent(static_cast<QMoveEvent*>(e)); return true; case QEvent::NonClientAreaMouseMove: @@ -287,7 +305,7 @@ bool QDockWidgetGroupWindow::event(QEvent *e) case QEvent::NonClientAreaMouseButtonRelease: case QEvent::NonClientAreaMouseButtonDblClick: // Let the QDockWidgetPrivate of the currently visible dock widget handle the drag and drop - if (QDockWidget *dw = topDockWidget()) + if (QDockWidget *dw = activeTabbedDockWidget()) static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->nonClientAreaMouseEvent(static_cast<QMouseEvent*>(e)); return true; case QEvent::ChildAdded: @@ -319,17 +337,49 @@ void QDockWidgetGroupWindow::paintEvent(QPaintEvent *) QDockAreaLayoutInfo *QDockWidgetGroupWindow::layoutInfo() const { - return static_cast<QDockWidgetGroupLayout*>(layout())->layoutInfo(); + return static_cast<QDockWidgetGroupLayout *>(layout())->dockAreaLayoutInfo(); +} + +/*! \internal + If this is a floating tab bar returns the currently the QDockWidgetGroupWindow that contains + tab, otherwise, return nullptr; + \note: if there is only one QDockWidget, it's still considered as a floating tab + */ +const QDockAreaLayoutInfo *QDockWidgetGroupWindow::tabLayoutInfo() const +{ + const QDockAreaLayoutInfo *info = layoutInfo(); + while (info && !info->tabbed) { + // There should be only one tabbed subinfo otherwise we are not a floating tab but a real + // window + const QDockAreaLayoutInfo *next = nullptr; + bool isSingle = false; + for (const auto &item : info->item_list) { + if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem)) + continue; + if (next || isSingle) // Two visible things + return nullptr; + if (item.subinfo) + next = item.subinfo; + else if (item.widgetItem) + isSingle = true; + } + if (isSingle) + return info; + info = next; + } + return info; } /*! \internal - Returns the currently active QDockWidget. + If this is a floating tab bar returns the currently active QDockWidget, otherwise nullptr */ -QDockWidget *QDockWidgetGroupWindow::topDockWidget() const +QDockWidget *QDockWidgetGroupWindow::activeTabbedDockWidget() const { - QDockAreaLayoutInfo *info = layoutInfo(); - QDockWidget *dw = 0; + QDockWidget *dw = nullptr; #if QT_CONFIG(tabbar) + const QDockAreaLayoutInfo *info = tabLayoutInfo(); + if (!info) + return nullptr; if (info->tabBar && info->tabBar->currentIndex() >= 0) { int i = info->tabIndexToListIndex(info->tabBar->currentIndex()); if (i >= 0) { @@ -338,7 +388,6 @@ QDockWidget *QDockWidgetGroupWindow::topDockWidget() const dw = qobject_cast<QDockWidget *>(item.widgetItem->widget()); } } -#endif if (!dw) { for (int i = 0; !dw && i < info->item_list.count(); ++i) { const QDockAreaLayoutItem &item = info->item_list.at(i); @@ -349,6 +398,7 @@ QDockWidget *QDockWidgetGroupWindow::topDockWidget() const dw = qobject_cast<QDockWidget *>(item.widgetItem->widget()); } } +#endif return dw; } @@ -395,18 +445,18 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty() } /*! \internal - Sets the flags of this window in accordence to the capabilities of the dock widgets + Sets the flags of this window in accordance to the capabilities of the dock widgets */ void QDockWidgetGroupWindow::adjustFlags() { - QDockWidget *top = topDockWidget(); - if (!top) - return; - const bool nativeDeco = static_cast<QDockWidgetGroupLayout *>(layout())->nativeWindowDeco(); - Qt::WindowFlags oldFlags = windowFlags(); Qt::WindowFlags flags = oldFlags; - if (nativeDeco) { + + QDockWidget *top = activeTabbedDockWidget(); + if (!top) { // nested tabs, show window decoration + flags = + ((oldFlags & ~Qt::FramelessWindowHint) | Qt::CustomizeWindowHint | Qt::WindowTitleHint); + } else if (static_cast<QDockWidgetGroupLayout *>(layout())->nativeWindowDeco()) { flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint; flags.setFlag(Qt::WindowCloseButtonHint, top->features() & QDockWidget::DockWidgetClosable); flags &= ~Qt::FramelessWindowHint; @@ -439,21 +489,99 @@ void QDockWidgetGroupWindow::adjustFlags() show(); // setWindowFlags hides the window } - setWindowTitle(top->windowTitle()); - setWindowIcon(top->windowIcon()); + QWidget *titleBarOf = top ? top : parentWidget(); + setWindowTitle(titleBarOf->windowTitle()); + setWindowIcon(titleBarOf->windowIcon()); } bool QDockWidgetGroupWindow::hasNativeDecos() const { + QDockWidget *dw = activeTabbedDockWidget(); + if (!dw) // We have a group of nested QDockWidgets (not just floating tabs) + return true; + if (!QDockWidgetLayout::wmSupportsNativeWindowDeco()) return false; - if (QDockWidget *dw = topDockWidget()) - return dw->titleBarWidget() == nullptr; + return dw->titleBarWidget() == nullptr; +} +/* + The given widget is hovered over this floating group. + This function will save the state and create a gap in the actual state. + currentGapRect and currentGapPos will be set. + One must call restore() or apply() after this function. + Returns true if there was any change in the currentGapPos + */ +bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mousePos) +{ + QDockAreaLayoutInfo &savedState = static_cast<QDockWidgetGroupLayout *>(layout())->savedState; + if (savedState.isEmpty()) + savedState = *layoutInfo(); + + QMainWindow::DockOptions opts = static_cast<QMainWindow *>(parentWidget())->dockOptions(); + bool nestingEnabled = + (opts & QMainWindow::AllowNestedDocks) && !(opts & QMainWindow::ForceTabbedDocks); + QDockAreaLayoutInfo::TabMode tabMode = + nestingEnabled ? QDockAreaLayoutInfo::AllowTabs : QDockAreaLayoutInfo::ForceTabs; + if (auto group = qobject_cast<QDockWidgetGroupWindow *>(widgetItem->widget())) { + if (!group->tabLayoutInfo()) + tabMode = QDockAreaLayoutInfo::NoTabs; + } + + QDockAreaLayoutInfo newState = savedState; + if (newState.tabbed) { + // insertion into a top-level tab + newState.item_list = { QDockAreaLayoutItem(new QDockAreaLayoutInfo(newState)) }; + newState.item_list.first().size = pick(savedState.o, savedState.rect.size()); + newState.tabbed = false; + newState.tabBar = nullptr; + } + + auto newGapPos = newState.gapIndex(mousePos, nestingEnabled, tabMode); + Q_ASSERT(!newGapPos.isEmpty()); + if (newGapPos == currentGapPos) + return false; // gap is already there + currentGapPos = newGapPos; + newState.insertGap(currentGapPos, widgetItem); + newState.fitItems(); + currentGapRect = newState.info(currentGapPos)->itemRect(currentGapPos.last(), true); + *layoutInfo() = std::move(newState); + layoutInfo()->apply(opts & QMainWindow::AnimatedDocks); return true; } +/* + Remove the gap that was created by hover() + */ +void QDockWidgetGroupWindow::restore() +{ + QDockAreaLayoutInfo &savedState = static_cast<QDockWidgetGroupLayout *>(layout())->savedState; + if (!savedState.isEmpty()) { + *layoutInfo() = savedState; + savedState = QDockAreaLayoutInfo(); + } + currentGapRect = QRect(); + currentGapPos.clear(); + adjustFlags(); + layoutInfo()->fitItems(); + layoutInfo()->apply(static_cast<QMainWindow *>(parentWidget())->dockOptions() + & QMainWindow::AnimatedDocks); +} + +/* + Apply the state that was created by hover + */ +void QDockWidgetGroupWindow::apply() +{ + static_cast<QDockWidgetGroupLayout *>(layout())->savedState.clear(); + currentGapRect = QRect(); + layoutInfo()->plug(currentGapPos); + currentGapPos.clear(); + adjustFlags(); + layoutInfo()->apply(false); +} + #endif /****************************************************************************** @@ -707,7 +835,14 @@ QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget, // is it a dock widget? if (qobject_cast<QDockWidget *>(widget) != 0 || qobject_cast<QDockWidgetGroupWindow *>(widget)) { - result = dockAreaLayout.gapIndex(pos); + bool disallowTabs = false; +#if QT_CONFIG(tabbar) + if (auto *group = qobject_cast<QDockWidgetGroupWindow *>(widget)) { + if (!group->tabLayoutInfo()) // Disallow to drop nested docks as a tab + disallowTabs = true; + } +#endif + result = dockAreaLayout.gapIndex(pos, disallowTabs); if (!result.isEmpty()) result.prepend(1); return result; @@ -1190,14 +1325,7 @@ void QMainWindowLayout::removeToolBar(QToolBar *toolbar) QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)), toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle))); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (usesHIToolBar(toolbar)) { - removeFromMacToolbar(toolbar); - } else -#endif - { - removeWidget(toolbar); - } + removeWidget(toolbar); } } @@ -1209,25 +1337,17 @@ void QMainWindowLayout::addToolBar(Qt::ToolBarArea area, bool) { validateToolBarArea(area); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if ((area == Qt::TopToolBarArea) - && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { - insertIntoMacToolbar(0, toolbar); - } else -#endif - { - //let's add the toolbar to the layout - addChildWidget(toolbar); - QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar); - if (savedState.isValid() && item) { - // copy the toolbar also in the saved state - savedState.toolBarAreaLayout.insertItem(toDockPos(area), item); - } - invalidate(); - - //this ensures that the toolbar has the right window flags (not floating any more) - toolbar->d_func()->updateWindowFlags(false /*floating*/); + // let's add the toolbar to the layout + addChildWidget(toolbar); + QLayoutItem *item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar); + if (savedState.isValid() && item) { + // copy the toolbar also in the saved state + savedState.toolBarAreaLayout.insertItem(toDockPos(area), item); } + invalidate(); + + // this ensures that the toolbar has the right window flags (not floating any more) + toolbar->d_func()->updateWindowFlags(false /*floating*/); } /*! @@ -1235,27 +1355,20 @@ void QMainWindowLayout::addToolBar(Qt::ToolBarArea area, */ void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (usesHIToolBar(before)) { - insertIntoMacToolbar(before, toolbar); - } else -#endif - { - addChildWidget(toolbar); - QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar); - if (savedState.isValid() && item) { - // copy the toolbar also in the saved state - savedState.toolBarAreaLayout.insertItem(before, item); + addChildWidget(toolbar); + QLayoutItem *item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar); + if (savedState.isValid() && item) { + // copy the toolbar also in the saved state + savedState.toolBarAreaLayout.insertItem(before, item); + } + if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) { + currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); + if (!currentGapPos.isEmpty()) { + currentGapPos.prepend(0); + currentGapRect = layoutState.itemRect(currentGapPos); } - if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) { - currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); - if (!currentGapPos.isEmpty()) { - currentGapPos.prepend(0); - currentGapRect = layoutState.itemRect(currentGapPos); - } - } - invalidate(); } + invalidate(); } Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const @@ -1268,12 +1381,6 @@ Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const case QInternal::BottomDock: return Qt::BottomToolBarArea; default: break; } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (pos == QInternal::DockCount) { - if (qtoolbarsInUnifiedToolbarList.contains(toolbar)) - return Qt::TopToolBarArea; - } -#endif return Qt::NoToolBarArea; } @@ -1290,70 +1397,15 @@ void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar void QMainWindowLayout::toggleToolBarsVisible() { - bool updateNonUnifiedParts = true; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { - // If we hit this case, someone has pressed the "toolbar button" which will - // toggle the unified toolbar visibility, because that's what the user wants. - // We might be in a situation where someone has hidden all the toolbars - // beforehand (maybe in construction), but now they've hit this button and - // and are expecting the items to show. What do we do? - // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this - // preserves what people would expect (these toolbars were visible when I clicked last time). - // 2) If NONE are visible, then show them all. Again, this preserves the user expectation - // of, "I want to see the toolbars." The user may get more toolbars than expected, but this - // is better seeing nothing. - // Don't worry about any of this if we are going invisible. This does mean we may get - // into issues when switching into and out of fullscreen mode, but this is probably minor. - // If we ever need to do hiding, that would have to be taken care of after the unified toolbar - // has finished hiding. - // People can of course handle the QEvent::ToolBarChange event themselves and do - // WHATEVER they want if they don't like what we are doing (though the unified toolbar - // will fire regardless). - - // Check if we REALLY need to update the geometry below. If we only have items in the - // unified toolbar, all the docks will be empty, so there's very little point - // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well). - // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar - // visibility can get out of sync. I really don't think it's a big issue. It is kept - // to a minimum because we only change the visibility if we absolutely must. - // update the "non unified parts." - updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty(); - - // We get this function before the unified toolbar does its thing. - // So, the value will be opposite of what we expect. - bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow)); - if (goingVisible) { - const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size(); - bool needAllVisible = true; - for (int i = 0; i < ToolBarCount; ++i) { - if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) { - needAllVisible = false; - break; - } - } - if (needAllVisible) { - QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because - // the toggle has already happened. - for (int i = 0; i < ToolBarCount; ++i) - qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true); - } - } - if (!updateNonUnifiedParts) - layoutState.toolBarAreaLayout.visible = goingVisible; - } -#endif - if (updateNonUnifiedParts) { - layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; - if (!layoutState.mainWindow->isMaximized()) { - QPoint topLeft = parentWidget()->geometry().topLeft(); - QRect r = parentWidget()->geometry(); - r = layoutState.toolBarAreaLayout.rectHint(r); - r.moveTo(topLeft); - parentWidget()->setGeometry(r); - } else { - update(); - } + layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; + if (!layoutState.mainWindow->isMaximized()) { + QPoint topLeft = parentWidget()->geometry().topLeft(); + QRect r = parentWidget()->geometry(); + r = layoutState.toolBarAreaLayout.rectHint(r); + r.moveTo(topLeft); + parentWidget()->setGeometry(r); + } else { + update(); } } @@ -1783,39 +1835,6 @@ void QMainWindowLayout::tabMoved(int from, int to) } #endif // QT_CONFIG(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) { #if QT_CONFIG(tabbar) @@ -1940,14 +1959,6 @@ QSize QMainWindowLayout::minimumSize() const const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0); minSize = QSize(qMax(sbMin.width(), minSize.width()), sbMin.height() + minSize.height()); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - const QSize storedSize = minSize; - int minWidth = 0; - foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) { - minWidth += toolbar->sizeHint().width() + 20; - } - minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height()); -#endif } return minSize; } @@ -1959,12 +1970,16 @@ void QMainWindowLayout::invalidate() } #if QT_CONFIG(dockwidget) -void QMainWindowLayout::setCurrentHoveredFloat(QWidget *w) +void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w) { if (currentHoveredFloat != w) { if (currentHoveredFloat) { disconnect(currentHoveredFloat.data(), &QObject::destroyed, this, &QMainWindowLayout::updateGapIndicator); + if (currentHoveredFloat) + currentHoveredFloat->restore(); + } else if (w) { + restore(true); } currentHoveredFloat = w; @@ -2035,52 +2050,30 @@ void QMainWindowLayout::revert(QLayoutItem *widgetItem) bool QMainWindowLayout::plug(QLayoutItem *widgetItem) { -#if QT_CONFIG(dockwidget) +#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget) && QT_CONFIG(tabbar) if (currentHoveredFloat) { QWidget *widget = widgetItem->widget(); QList<int> previousPath = layoutState.indexOf(widget); if (!previousPath.isEmpty()) layoutState.remove(previousPath); + previousPath = currentHoveredFloat->layoutInfo()->indexOf(widget); // Let's remove the widget from any possible group window foreach (QDockWidgetGroupWindow *dwgw, parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) { + if (dwgw == currentHoveredFloat) + continue; QList<int> path = dwgw->layoutInfo()->indexOf(widget); if (!path.isEmpty()) dwgw->layoutInfo()->remove(path); } currentGapRect = QRect(); -#if QT_CONFIG(tabwidget) - if (QDockWidget *dropTo = qobject_cast<QDockWidget*>(currentHoveredFloat)) { - //dropping to a normal widget, we mutate it in a QDockWidgetGroupWindow with two tabs - QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow(); - floatingTabs->setGeometry(dropTo->geometry()); - QDockAreaLayoutInfo *info = floatingTabs->layoutInfo(); - *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, QInternal::LeftDock, - Qt::Horizontal, QTabBar::RoundedSouth, - static_cast<QMainWindow*>(parentWidget())); - info->tabbed = true; - QLayout *parentLayout = currentHoveredFloat->parentWidget()->layout(); - info->item_list.append(QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(currentHoveredFloat)))); - - dropTo->setParent(floatingTabs); - dropTo->show(); - dropTo->d_func()->plug(QRect()); - setCurrentHoveredFloat(floatingTabs); - } -#endif // QT_CONFIG(tabwidget) -#if QT_CONFIG(tabbar) - QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(currentHoveredFloat); - Q_ASSERT(dwgw); - Q_ASSERT(dwgw->layoutInfo()->tabbed); // because floating group should always be tabbed - previousPath = dwgw->layoutInfo()->indexOf(widget); + currentHoveredFloat->apply(); if (!previousPath.isEmpty()) - dwgw->layoutInfo()->remove(previousPath); - dwgw->layoutInfo()->tab(0, widgetItem); - QRect globalRect = dwgw->layoutInfo()->tabContentRect(); - globalRect.moveTopLeft(dwgw->mapToGlobal(globalRect.topLeft())); + currentHoveredFloat->layoutInfo()->remove(previousPath); + QRect globalRect = currentHoveredFloat->currentGapRect; + globalRect.moveTopLeft(currentHoveredFloat->mapToGlobal(globalRect.topLeft())); pluggingWidget = widget; widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks); -#endif // QT_CONFIG(tabbar) return true; } #endif @@ -2149,57 +2142,55 @@ void QMainWindowLayout::animationFinished(QWidget *widget) if (widget == pluggingWidget) { #if QT_CONFIG(dockwidget) +#if QT_CONFIG(tabbar) if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) { // When the animated widget was a QDockWidgetGroupWindow, it means each of the // embedded QDockWidget needs to be plugged back into the QMainWindow layout. savedState.clear(); - QDockAreaLayoutInfo* info = dwgw->layoutInfo(); - QDockAreaLayoutInfo* parentInfo; - QList<int> path; - - if (QDockWidgetGroupWindow *dropTo = qobject_cast<QDockWidgetGroupWindow *>(currentHoveredFloat)) { - parentInfo = dropTo->layoutInfo(); -#if QT_CONFIG(tabbar) - Q_ASSERT(parentInfo->tabbed); -#endif - path = parentInfo->indexOf(widget); - Q_ASSERT(path.size() == 1); + QDockAreaLayoutInfo *srcInfo = dwgw->layoutInfo(); + const QDockAreaLayoutInfo *srcTabInfo = dwgw->tabLayoutInfo(); + QDockAreaLayoutInfo *dstParentInfo; + QList<int> dstPath; + + if (currentHoveredFloat) { + dstPath = currentHoveredFloat->layoutInfo()->indexOf(widget); + Q_ASSERT(dstPath.size() >= 1); + dstParentInfo = currentHoveredFloat->layoutInfo()->info(dstPath); } else { - path = layoutState.dockAreaLayout.indexOf(widget); - Q_ASSERT(path.size() >= 2); - parentInfo = layoutState.dockAreaLayout.info(path); - Q_ASSERT(parentInfo); + dstPath = layoutState.dockAreaLayout.indexOf(widget); + Q_ASSERT(dstPath.size() >= 2); + dstParentInfo = layoutState.dockAreaLayout.info(dstPath); } -#if QT_CONFIG(tabbar) - if (parentInfo->tabbed) { + Q_ASSERT(dstParentInfo); + int idx = dstPath.constLast(); + Q_ASSERT(dstParentInfo->item_list[idx].widgetItem->widget() == dwgw); + if (dstParentInfo->tabbed && srcTabInfo) { // merge the two tab widgets - int idx = path.constLast(); - Q_ASSERT(parentInfo->item_list[idx].widgetItem->widget() == dwgw); - delete parentInfo->item_list[idx].widgetItem; - parentInfo->item_list.removeAt(idx); - std::copy(info->item_list.cbegin(), info->item_list.cend(), - std::inserter(parentInfo->item_list, parentInfo->item_list.begin() + idx)); - quintptr currentId = info->currentTabId(); - *info = QDockAreaLayoutInfo(); - parentInfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data() : parentWidget()); - parentInfo->updateTabBar(); - parentInfo->setCurrentTabId(currentId); - } else -#endif // QT_CONFIG(tabbar) - { - QDockAreaLayoutItem &item = layoutState.dockAreaLayout.item(path); + delete dstParentInfo->item_list[idx].widgetItem; + dstParentInfo->item_list.removeAt(idx); + std::copy(srcTabInfo->item_list.cbegin(), srcTabInfo->item_list.cend(), + std::inserter(dstParentInfo->item_list, + dstParentInfo->item_list.begin() + idx)); + quintptr currentId = srcTabInfo->currentTabId(); + *srcInfo = QDockAreaLayoutInfo(); + dstParentInfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data() + : parentWidget()); + dstParentInfo->updateTabBar(); + dstParentInfo->setCurrentTabId(currentId); + } else { + QDockAreaLayoutItem &item = dstParentInfo->item_list[idx]; Q_ASSERT(item.widgetItem->widget() == dwgw); delete item.widgetItem; item.widgetItem = 0; - item.subinfo = new QDockAreaLayoutInfo(qMove(*info)); - *info = QDockAreaLayoutInfo(); -#if QT_CONFIG(tabbar) - item.subinfo->reparentWidgets(parentWidget()); - item.subinfo->setTabBarShape(parentInfo->tabBarShape); -#endif + item.subinfo = new QDockAreaLayoutInfo(std::move(*srcInfo)); + *srcInfo = QDockAreaLayoutInfo(); + item.subinfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data() + : parentWidget()); + item.subinfo->setTabBarShape(dstParentInfo->tabBarShape); } dwgw->destroyOrHideIfEmpty(); } +#endif if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) { dw->setParent(currentHoveredFloat ? currentHoveredFloat.data() : parentWidget()); @@ -2279,9 +2270,6 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLay #endif // QT_CONFIG(dockwidget) , widgetAnimator(this) , pluggingWidget(0) -#if 0 // Used to be included in Qt4 for Q_WS_MAC - , blockVisiblityCheck(false) -#endif { if (parentLayout) setParent(parentLayout); @@ -2306,10 +2294,6 @@ QMainWindowLayout::~QMainWindowLayout() layoutState.deleteAllLayoutItems(); layoutState.deleteCentralWidgetItem(); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - cleanUpMacToolbarItems(); -#endif - delete statusbar; } @@ -2362,6 +2346,36 @@ void QMainWindowLayout::setCentralWidget(QWidget *widget) invalidate(); } +#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget) +/*! \internal + This helper function is called by QMainWindowLayout::unplug if QMainWindow::GroupedDragging is + set and we are dragging the title bar of a non-floating QDockWidget. + If one should unplug the whole group, do so and return true, otherwise return false. + \a item is pointing to the QLayoutItem that holds the QDockWidget, but will be updated to the + QLayoutItem that holds the new QDockWidgetGroupWindow if the group is unplugged. +*/ +static bool unplugGroup(QMainWindowLayout *layout, QLayoutItem **item, + QDockAreaLayoutItem &parentItem) +{ + if (!parentItem.subinfo || !parentItem.subinfo->tabbed) + return false; + + // The QDockWidget is part of a group of tab and we need to unplug them all. + + QDockWidgetGroupWindow *floatingTabs = layout->createTabbedDockWindow(); + QDockAreaLayoutInfo *info = floatingTabs->layoutInfo(); + *info = std::move(*parentItem.subinfo); + delete parentItem.subinfo; + parentItem.subinfo = nullptr; + floatingTabs->setGeometry(info->rect.translated(layout->parentWidget()->pos())); + floatingTabs->show(); + floatingTabs->raise(); + *item = new QDockWidgetGroupWindowItem(floatingTabs); + parentItem.widgetItem = *item; + return true; +} +#endif + /*! \internal Unplug \a widget (QDockWidget or QToolBar) from it's parent container. @@ -2375,19 +2389,31 @@ void QMainWindowLayout::setCentralWidget(QWidget *widget) QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group) { #if QT_CONFIG(dockwidget) && QT_CONFIG(tabbar) - if (!widget->isWindow() && qobject_cast<const QDockWidgetGroupWindow *>(widget->parentWidget())) { - if (group) { + auto *groupWindow = qobject_cast<const QDockWidgetGroupWindow *>(widget->parentWidget()); + if (!widget->isWindow() && groupWindow) { + if (group && groupWindow->tabLayoutInfo()) { // We are just dragging a floating window as it, not need to do anything, we just have to // look up the corresponding QWidgetItem* if it exists - QList<int> tabbedWindowPath = layoutState.indexOf(widget->parentWidget()); - return tabbedWindowPath.isEmpty() ? 0 : layoutState.item(tabbedWindowPath); + if (QDockAreaLayoutInfo *info = dockInfo(widget->parentWidget())) { + QList<int> groupWindowPath = info->indexOf(widget->parentWidget()); + return groupWindowPath.isEmpty() ? nullptr : info->item(groupWindowPath).widgetItem; + } + return nullptr; + } + QList<int> path = groupWindow->layoutInfo()->indexOf(widget); + QLayoutItem *item = groupWindow->layoutInfo()->item(path).widgetItem; + if (group && path.size() > 1 + && unplugGroup(this, &item, + groupWindow->layoutInfo()->item(path.mid(0, path.size() - 1)))) { + return item; } else { // We are unplugging a dock widget from a floating window. - if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) { - dw->d_func()->unplug(widget->geometry()); - int index = widget->parentWidget()->layout()->indexOf(widget); - return widget->parentWidget()->layout()->itemAt(index); - } + QDockWidget *dw = qobject_cast<QDockWidget *>(widget); + Q_ASSERT(dw); // cannot be a QDockWidgetGroupWindow because it's not floating. + dw->d_func()->unplug(widget->geometry()); + groupWindow->layoutInfo()->fitItems(); + groupWindow->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks); + return item; } } #endif @@ -2405,30 +2431,15 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group) #if QT_CONFIG(dockwidget) if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) { Q_ASSERT(path.constFirst() == 1); - bool actualGroup = false; #if QT_CONFIG(tabwidget) - if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3) { - QDockAreaLayoutItem &parentItem = layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2)); - if (parentItem.subinfo && parentItem.subinfo->tabbed) { - // The QDockWidget is part of a group of tab and we need to unplug them all. - actualGroup = true; - path.removeLast(); - - QDockWidgetGroupWindow* floatingTabs = createTabbedDockWindow(); - QDockAreaLayoutInfo* info = floatingTabs->layoutInfo(); - *info = qMove(*parentItem.subinfo); - delete parentItem.subinfo; - parentItem.subinfo = 0; - floatingTabs->setGeometry(info->rect.translated(parentWidget()->pos())); - floatingTabs->show(); - floatingTabs->raise(); - item = new QDockWidgetGroupWindowItem(floatingTabs); - parentItem.widgetItem = item; - savedState = layoutState; - } - } + if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3 + && unplugGroup(this, &item, + layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2)))) { + path.removeLast(); + savedState = layoutState; + } else #endif // QT_CONFIG(tabwidget) - if (!actualGroup) { + { dw->d_func()->unplug(r); } } @@ -2457,11 +2468,11 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group) void QMainWindowLayout::updateGapIndicator() { #if QT_CONFIG(rubberband) - if ((!widgetAnimator.animating() && !currentGapPos.isEmpty()) + if (!widgetAnimator.animating() && (!currentGapPos.isEmpty() #if QT_CONFIG(dockwidget) - || currentHoveredFloat + || currentHoveredFloat #endif - ) { + )) { QWidget *expectedParent = #if QT_CONFIG(dockwidget) currentHoveredFloat ? currentHoveredFloat.data() : @@ -2474,11 +2485,13 @@ void QMainWindowLayout::updateGapIndicator() } else if (gapIndicator->parent() != expectedParent) { gapIndicator->setParent(expectedParent); } - gapIndicator->setGeometry( + #if QT_CONFIG(dockwidget) - currentHoveredFloat ? currentHoveredFloat->rect() : + if (currentHoveredFloat) + gapIndicator->setGeometry(currentHoveredFloat->currentGapRect); + else #endif - currentGapRect); + gapIndicator->setGeometry(currentGapRect); gapIndicator->show(); gapIndicator->raise(); } else if (gapIndicator) { @@ -2527,12 +2540,36 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) if (!w->geometry().contains(mousePos)) continue; - setCurrentHoveredFloat(w); - restore(true); + if (auto dropTo = qobject_cast<QDockWidget *>(w)) { + // dropping to a normal widget, we mutate it in a QDockWidgetGroupWindow with two + // tabs + QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow(); // FIXME + floatingTabs->setGeometry(dropTo->geometry()); + QDockAreaLayoutInfo *info = floatingTabs->layoutInfo(); + *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, QInternal::LeftDock, + Qt::Horizontal, QTabBar::RoundedSouth, + static_cast<QMainWindow *>(parentWidget())); + info->tabbed = true; + QLayout *parentLayout = dropTo->parentWidget()->layout(); + info->item_list.append( + QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo)))); + + dropTo->setParent(floatingTabs); + dropTo->show(); + dropTo->d_func()->plug(QRect()); + w = floatingTabs; + } + Q_ASSERT(qobject_cast<QDockWidgetGroupWindow *>(w)); + auto group = static_cast<QDockWidgetGroupWindow *>(w); + if (group->hover(widgetItem, group->mapFromGlobal(mousePos))) { + setCurrentHoveredFloat(group); + applyState(layoutState); // update the tabbars + } return; } } setCurrentHoveredFloat(nullptr); + layoutState.dockAreaLayout.fallbackToSizeHints = false; #endif // QT_CONFIG(dockwidget) QPoint pos = parentWidget()->mapFromGlobal(mousePos); @@ -2595,7 +2632,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) #if QT_CONFIG(dockwidget) parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); #endif - layoutState = newState; + layoutState = std::move(newState); applyState(layoutState); updateGapIndicator(); @@ -2684,45 +2721,6 @@ bool QMainWindowLayout::restoreState(QDataStream &stream) return true; } - -// Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases -// for example, you have a toolbar in the top area and then you suddenly turn on -// HIToolbar. -bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const -{ -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC - Q_UNUSED(toolbar); - return false; -#else - return qtoolbarsInUnifiedToolbarList.contains(toolbar) - || ((toolBarArea(toolbar) == Qt::TopToolBarArea) - && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()); -#endif -} - -void QMainWindowLayout::timerEvent(QTimerEvent *e) -{ -#if QT_CONFIG(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 615035d2fe..c61c4f6aa8 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -57,6 +57,8 @@ #include "QtWidgets/qlayout.h" #if QT_CONFIG(tabbar) #include "QtWidgets/qtabbar.h" +#include "QtGui/qpainter.h" +#include "QtGui/qevent.h" #endif #include "QtCore/qvector.h" #include "QtCore/qset.h" @@ -76,6 +78,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 + #if QT_CONFIG(dockwidget) class QDockWidgetGroupWindow : public QWidget { @@ -84,11 +331,19 @@ public: explicit QDockWidgetGroupWindow(QWidget* parent = 0, Qt::WindowFlags f = 0) : QWidget(parent, f) {} QDockAreaLayoutInfo *layoutInfo() const; - QDockWidget *topDockWidget() const; + const QDockAreaLayoutInfo *tabLayoutInfo() const; + QDockWidget *activeTabbedDockWidget() const; void destroyOrHideIfEmpty(); void adjustFlags(); bool hasNativeDecos() const; + bool hover(QLayoutItem *widgetItem, const QPoint &mousePos); + void restore(); + void apply(); + + QRect currentGapRect; + QList<int> currentGapPos; + protected: bool event(QEvent *) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE; @@ -172,7 +427,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 @@ -184,9 +441,6 @@ public: QMainWindow::DockOptions dockOptions; void setDockOptions(QMainWindow::DockOptions opts); - bool usesHIToolBar(QToolBar *toolbar) const; - - void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; // status bar @@ -265,15 +519,7 @@ public: #endif // QT_CONFIG(tabwidget) #endif // QT_CONFIG(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_CONFIG(dockwidget) @@ -309,8 +555,8 @@ public: QPointer<QRubberBand> gapIndicator; #endif #if QT_CONFIG(dockwidget) - QPointer<QWidget> currentHoveredFloat; // set when dragging over a floating dock widget - void setCurrentHoveredFloat(QWidget *w); + QPointer<QDockWidgetGroupWindow> currentHoveredFloat; // set when dragging over a floating dock widget + void setCurrentHoveredFloat(QDockWidgetGroupWindow *w); #endif void hover(QLayoutItem *widgetItem, const QPoint &mousePos); @@ -320,7 +566,6 @@ public: void paintDropIndicator(QPainter *p, QWidget *widget, const QRegion &clip); void applyState(QMainWindowLayoutState &newState, bool animate = true); void restore(bool keepSavedState = false); - void updateHIToolBarStatus(); void animationFinished(QWidget *widget); private Q_SLOTS: @@ -335,40 +580,6 @@ private: #if QT_CONFIG(tabbar) void updateTabBarShapes(); #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - static OSStatus qtmacToolbarDelegate(EventHandlerCallRef, EventRef , void *); - static OSStatus qtoolbarInHIToolbarHandler(EventHandlerCallRef inCallRef, EventRef event, - void *data); - static void qtMacHIToolbarRegisterQToolBarInHIToolborItemClass(); - static HIToolbarItemRef CreateToolbarItemForIdentifier(CFStringRef identifier, CFTypeRef data); - static HIToolbarItemRef createQToolBarInHIToolbarItem(QToolBar *toolbar, - QMainWindowLayout *layout); -public: - struct ToolBarSaveState { - ToolBarSaveState() : movable(false) { } - ToolBarSaveState(bool newMovable, const QSize &newMax) - : movable(newMovable), maximumSize(newMax) { } - bool movable; - QSize maximumSize; - }; - QList<QToolBar *> qtoolbarsInUnifiedToolbarList; - QList<void *> toolbarItemsCopy; - QHash<void *, QToolBar *> unifiedToolbarHash; - QHash<QToolBar *, ToolBarSaveState> toolbarSaveState; - QHash<QString, QToolBar *> cocoaItemIDToToolbarHash; - void insertIntoMacToolbar(QToolBar *before, QToolBar *after); - void removeFromMacToolbar(QToolBar *toolbar); - void cleanUpMacToolbarItems(); - void fixSizeInUnifiedToolbar(QToolBar *tb) const; - bool useHIToolBar; - bool activateUnifiedToolbarAfterFullScreen; - void syncUnifiedToolbarVisibility(); - bool blockVisiblityCheck; - - QUnifiedToolbarSurface *unifiedSurface; - void updateUnifiedToolbarOffset(); - -#endif }; #if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM) diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index c90d915f4c..4e7925556a 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -158,9 +158,6 @@ #include <QApplication> #include <QStyle> -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(style_mac) -#include <private/qmacstyle_mac_p.h> -#endif #include <QChildEvent> #include <QResizeEvent> #include <QScrollBar> @@ -169,6 +166,7 @@ #include <QFontMetrics> #include <QStyleOption> #include <QDesktopWidget> +#include <private/qdesktopwidget_p.h> #include <QDebug> #include <qmath.h> #if QT_CONFIG(menu) @@ -1750,7 +1748,7 @@ QSize QMdiArea::sizeHint() const } const int scaleFactor = 3 * (nestedCount + 1); - QSize desktopSize = QApplication::desktop()->size(); + QSize desktopSize = QDesktopWidgetPrivate::size(); QSize size(desktopSize.width() * 2 / scaleFactor, desktopSize.height() * 2 / scaleFactor); for (QMdiSubWindow *child : d_func()->childWindows) { if (!sanityCheck(child, "QMdiArea::sizeHint")) diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp index 2e6c82f95a..129898a08d 100644 --- a/src/widgets/widgets/qmdisubwindow.cpp +++ b/src/widgets/widgets/qmdisubwindow.cpp @@ -160,9 +160,6 @@ #endif #include <QScrollBar> #include <QDebug> -#if QT_CONFIG(style_mac) -#include <private/qmacstyle_mac_p.h> -#endif #include <QMdiArea> #include <QScopedValueRollback> #include <QAction> @@ -200,6 +197,11 @@ static const Qt::WindowFlags CustomizeWindowFlags = static const int BoundaryMargin = 5; +static inline bool isMacStyle(QStyle *style) +{ + return style->inherits("QMacStyle"); +} + static inline int getMoveDeltaComponent(uint cflags, uint moveFlag, uint resizeFlag, int delta, int maxDelta, int minDelta) { @@ -301,11 +303,8 @@ static void showToolTip(QHelpEvent *helpEvent, QWidget *widget, const QStyleOpti Q_ASSERT(helpEvent->type() == QEvent::ToolTip); Q_ASSERT(widget); -#if QT_CONFIG(style_mac) - // Native Mac windows don't show tool tip. - if (qobject_cast<QMacStyle *>(widget->style())) + if (widget->style()->styleHint(QStyle::SH_TitleBar_ShowToolTipsOnButtons, &opt, widget)) return; -#endif // Convert CC_MdiControls to CC_TitleBar. Sub controls of different complex // controls cannot be in the same switch as they might have the same value. @@ -1082,10 +1081,8 @@ void QMdiSubWindowPrivate::updateCursor() { #ifndef QT_NO_CURSOR Q_Q(QMdiSubWindow); -#if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) + if (isMacStyle(q->style())) return; -#endif if (currentOperation == None) { q->unsetCursor(); @@ -1510,15 +1507,14 @@ void QMdiSubWindowPrivate::processClickedSubControl() q->showNormal(); break; case QStyle::SC_TitleBarMinButton: -#if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) { + if (isMacStyle(q->style())) { if (q->isMinimized()) q->showNormal(); else q->showMinimized(); break; } -#endif + q->showMinimized(); break; case QStyle::SC_TitleBarNormalButton: @@ -1527,15 +1523,14 @@ void QMdiSubWindowPrivate::processClickedSubControl() q->showNormal(); break; case QStyle::SC_TitleBarMaxButton: -#if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) { + if (isMacStyle(q->style())) { if (q->isMaximized()) q->showNormal(); else q->showMaximized(); break; } -#endif + q->showMaximized(); break; case QStyle::SC_TitleBarCloseButton: @@ -1574,10 +1569,8 @@ QRegion QMdiSubWindowPrivate::getRegion(Operation operation) const } QRegion region; -#if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) + if (isMacStyle(q->style())) return region; -#endif switch (operation) { case TopResize: @@ -1781,10 +1774,6 @@ bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized() const if (isChildOfTabbedQMdiArea(q)) return false; -#if QT_CONFIG(style_mac) - Q_UNUSED(isChildOfQMdiSubWindow); - return true; -#else if (q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q)) return true; #if !QT_CONFIG(menubar) || !QT_CONFIG(mainwindow) @@ -1798,7 +1787,6 @@ bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized() const return isChildOfQMdiSubWindow(q); #endif -#endif } #if QT_CONFIG(menubar) @@ -2197,10 +2185,8 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip) return; newSizeGrip->setFixedSize(newSizeGrip->sizeHint()); bool putSizeGripInLayout = layout ? true : false; -#if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(q->style())) + if (isMacStyle(q->style())) putSizeGripInLayout = false; -#endif if (putSizeGripInLayout) { layout->addWidget(newSizeGrip); layout->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight); @@ -2849,8 +2835,8 @@ bool QMdiSubWindow::event(QEvent *event) d->isMaximizeMode = false; d->isWidgetHiddenByUs = false; if (!parent()) { -#if QT_CONFIG(sizegrip) && QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(style())) +#if QT_CONFIG(sizegrip) + if (isMacStyle(style())) delete d->sizeGrip; #endif setOption(RubberBandResize, false); @@ -2944,8 +2930,8 @@ void QMdiSubWindow::showEvent(QShowEvent *showEvent) return; } -#if QT_CONFIG(sizegrip) && QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(style()) && !d->sizeGrip +#if QT_CONFIG(sizegrip) + if (isMacStyle(style()) && !d->sizeGrip && !(windowFlags() & Qt::FramelessWindowHint)) { d->setSizeGrip(new QSizeGrip(this)); Q_ASSERT(d->sizeGrip); @@ -3339,10 +3325,10 @@ void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent) hoverRegion += style()->subControlRect(QStyle::CC_TitleBar, &options, d->hoveredSubControl, this); } -#if QT_CONFIG(style_mac) - if (qobject_cast<QMacStyle *>(style()) && !hoverRegion.isEmpty()) + + if (isMacStyle(style()) && !hoverRegion.isEmpty()) hoverRegion += QRegion(0, 0, width(), d->titleBarHeight(options)); -#endif + if (!hoverRegion.isEmpty()) update(hoverRegion); } @@ -3549,10 +3535,8 @@ QSize QMdiSubWindow::minimumSizeHint() const int sizeGripHeight = 0; if (d->sizeGrip && d->sizeGrip->isVisibleTo(const_cast<QMdiSubWindow *>(this))) sizeGripHeight = d->sizeGrip->height(); -#if QT_CONFIG(style_mac) - else if (parent() && qobject_cast<QMacStyle *>(style()) && !d->sizeGrip) + else if (parent() && isMacStyle(style()) && !d->sizeGrip) sizeGripHeight = style()->pixelMetric(QStyle::PM_SizeGripSize, 0, this); -#endif minHeight = qMax(minHeight, decorationHeight + sizeGripHeight); #endif diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 196348f8e8..ded218de73 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -77,6 +77,7 @@ #include <private/qaction_p.h> #include <private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> +#include <private/qdesktopwidget_p.h> QT_BEGIN_NAMESPACE @@ -102,7 +103,7 @@ class QTornOffMenu : public QMenu Q_Q(QTornOffMenu); QSize size = menuSize; const QPoint p = (!initialized) ? causedMenu->pos() : q->pos(); - QRect screen = popupGeometry(QApplication::desktop()->screenNumber(p)); + QRect screen = popupGeometry(QDesktopWidgetPrivate::screenNumber(p)); const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q); const int titleBarHeight = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, 0, q); if (scroll && (size.height() > screen.height() - titleBarHeight || size.width() > screen.width())) { @@ -264,28 +265,28 @@ int QMenuPrivate::scrollerHeight() const return qMax(QApplication::globalStrut().height(), q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q)); } -//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't +//Windows and KDE allow menus to cover the taskbar, while GNOME and Mac don't QRect QMenuPrivate::popupGeometry() const { Q_Q(const QMenu); if (!tornoff && // Torn-off menus are different QGuiApplicationPrivate::platformTheme() && QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool()) { - return QApplication::desktop()->screenGeometry(q); + return QDesktopWidgetPrivate::screenGeometry(q); } else { - return QApplication::desktop()->availableGeometry(q); + return QDesktopWidgetPrivate::availableGeometry(q); } } -//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't +//Windows and KDE allow menus to cover the taskbar, while GNOME and Mac don't QRect QMenuPrivate::popupGeometry(int screen) const { if (!tornoff && // Torn-off menus are different QGuiApplicationPrivate::platformTheme() && QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::UseFullScreenForPopupMenu).toBool()) { - return QApplication::desktop()->screenGeometry(screen); + return QDesktopWidgetPrivate::screenGeometry(screen); } else { - return QApplication::desktop()->availableGeometry(screen); + return QDesktopWidgetPrivate::availableGeometry(screen); } } @@ -304,6 +305,11 @@ QVector<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const return ret; } +bool QMenuPrivate::isContextMenu() const +{ + return qobject_cast<const QMenuBar *>(topCausedWidget()) == nullptr; +} + void QMenuPrivate::updateActionRects() const { updateActionRects(popupGeometry()); @@ -358,6 +364,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const //calculate size QFontMetrics qfm = q->fontMetrics(); bool previousWasSeparator = true; // this is true to allow removing the leading separators + const bool contextMenu = isContextMenu(); for(int i = 0; i <= lastVisibleAction; i++) { QAction *action = actions.at(i); const bool isSection = action->isSeparator() && (!action->text().isEmpty() || !action->icon().isNull()); @@ -389,7 +396,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const tabWidth = qMax(int(tabWidth), qfm.width(s.mid(t+1))); s = s.left(t); #ifndef QT_NO_SHORTCUT - } else { + } else if (action->isShortcutVisibleInContextMenu() || !contextMenu) { QKeySequence seq = action->shortcut(); if (!seq.isEmpty()) tabWidth = qMax(int(tabWidth), qfm.width(seq.toString(QKeySequence::NativeText))); @@ -1537,7 +1544,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) option->icon = action->icon(); QString textAndAccel = action->text(); #ifndef QT_NO_SHORTCUT - if (textAndAccel.indexOf(QLatin1Char('\t')) == -1) { + if ((action->isShortcutVisibleInContextMenu() || !d->isContextMenu()) + && textAndAccel.indexOf(QLatin1Char('\t')) == -1) { QKeySequence seq = action->shortcut(); if (!seq.isEmpty()) textAndAccel += QLatin1Char('\t') + seq.toString(QKeySequence::NativeText); @@ -2348,7 +2356,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction) screen = d->popupGeometry(); else #endif - screen = d->popupGeometry(QApplication::desktop()->screenNumber(p)); + screen = d->popupGeometry(QDesktopWidgetPrivate::screenNumber(p)); d->updateActionRects(screen); QPoint pos; @@ -2448,8 +2456,6 @@ void QMenu::popup(const QPoint &p, QAction *atAction) pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1)); else pos.setY(qMax(p.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1)); - } else if (pos.y() < screen.top() + desktopFrame) { - pos.setY(screen.top() + desktopFrame); } if (pos.y() < screen.top() + desktopFrame) @@ -2681,7 +2687,8 @@ void QMenu::hideEvent(QHideEvent *) if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget)) mb->d_func()->setCurrentAction(0); #endif - d->mouseDown = 0; + if (d->mouseDown == this) + d->mouseDown = 0; d->hasHadMouse = false; if (d->activeMenu) d->hideMenu(d->activeMenu); @@ -3618,7 +3625,7 @@ void QMenu::internalDelayedPopup() screen = d->popupGeometry(); else #endif - screen = d->popupGeometry(QApplication::desktop()->screenNumber(pos())); + screen = d->popupGeometry(QDesktopWidgetPrivate::screenNumber(pos())); int subMenuOffset = style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, this); const QRect actionRect(d->actionRect(d->currentAction)); diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h index 0b5ed579cd..7cf73f55b3 100644 --- a/src/widgets/widgets/qmenu.h +++ b/src/widgets/widgets/qmenu.h @@ -107,7 +107,7 @@ public: #else result->setShortcut(shortcut); #endif - connect(result, &QAction::triggered, object, slot); + connect(result, &QAction::triggered, object, std::move(slot)); return result; } // addAction(QString): Connect to a functor or function pointer (without context) @@ -120,7 +120,7 @@ public: #else result->setShortcut(shortcut); #endif - connect(result, &QAction::triggered, slot); + connect(result, &QAction::triggered, std::move(slot)); return result; } // addAction(QIcon, QString): Connect to a QObject slot / functor or function pointer (with context) @@ -135,7 +135,7 @@ public: #else result->setShortcut(shortcut); #endif - connect(result, &QAction::triggered, object, slot); + connect(result, &QAction::triggered, object, std::move(slot)); return result; } // addAction(QIcon, QString): Connect to a functor or function pointer (without context) @@ -148,7 +148,7 @@ public: #else result->setShortcut(shortcut); #endif - connect(result, &QAction::triggered, slot); + connect(result, &QAction::triggered, std::move(slot)); return result; } #endif // !Q_QDOC diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 4b7ce05169..5869bc8420 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -309,6 +309,8 @@ public: static QMenuPrivate *get(QMenu *m) { return m->d_func(); } int scrollerHeight() const; + bool isContextMenu() const; + //item calculations mutable uint itemsDirty : 1; mutable uint maxIconWidth, tabWidth; diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 41b6bf49f8..cc6f39c439 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -62,6 +62,7 @@ #include <qpa/qplatformtheme.h> #include "private/qguiapplication_p.h" #include "qpa/qplatformintegration.h" +#include <private/qdesktopwidget_p.h> #include "qmenu_p.h" #include "qmenubar_p.h" @@ -321,7 +322,7 @@ void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst) QSize popup_size = activeMenu->sizeHint(); //we put the popup menu on the screen containing the bottom-center of the action rect - QRect screenRect = QApplication::desktop()->screenGeometry(pos + QPoint(adjustedActionRect.width() / 2, 0)); + QRect screenRect = QDesktopWidgetPrivate::screenGeometry(pos + QPoint(adjustedActionRect.width() / 2, 0)); pos = QPoint(qMax(pos.x(), screenRect.x()), qMax(pos.y(), screenRect.y())); const bool fitUp = (q->mapToGlobal(adjustedActionRect.topLeft()).y() >= popup_size.height()); @@ -1565,7 +1566,7 @@ QSize QMenuBar::minimumSizeHint() const int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this); int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this); if(as_gui_menubar) { - int w = parentWidget() ? parentWidget()->width() : QApplication::desktop()->width(); + int w = parentWidget() ? parentWidget()->width() : QDesktopWidgetPrivate::width(); d->calcActionRects(w - (2 * fw), 0); for (int i = 0; ret.isNull() && i < d->actions.count(); ++i) ret = d->actionRects.at(i).size(); @@ -1617,7 +1618,7 @@ QSize QMenuBar::sizeHint() const int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this); int spaceBelowMenuBar = style()->styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, 0, this); if(as_gui_menubar) { - const int w = parentWidget() ? parentWidget()->width() : QApplication::desktop()->width(); + const int w = parentWidget() ? parentWidget()->width() : QDesktopWidgetPrivate::width(); d->calcActionRects(w - (2 * fw), 0); for (int i = 0; i < d->actionRects.count(); ++i) { const QRect &actionRect = d->actionRects.at(i); diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 6b51388990..555b1f94ad 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -2453,29 +2453,51 @@ void QPlainTextEdit::setOverwriteMode(bool overwrite) d->control->setOverwriteMode(overwrite); } +#if QT_DEPRECATED_SINCE(5, 10) /*! \property QPlainTextEdit::tabStopWidth \brief the tab stop width in pixels + \deprecated in Qt 5.10. Use tabStopDistance instead. By default, this property contains a value of 80. */ int QPlainTextEdit::tabStopWidth() const { - Q_D(const QPlainTextEdit); - return qRound(d->control->document()->defaultTextOption().tabStop()); + return qRound(tabStopDistance()); } void QPlainTextEdit::setTabStopWidth(int width) { + setTabStopDistance(width); +} +#endif + +/*! + \property QPlainTextEdit::tabStopDistance + \brief the tab stop distance in pixels + \since 5.10 + + By default, this property contains a value of 80. +*/ + +qreal QPlainTextEdit::tabStopDistance() const +{ + Q_D(const QPlainTextEdit); + return d->control->document()->defaultTextOption().tabStopDistance(); +} + +void QPlainTextEdit::setTabStopDistance(qreal distance) +{ Q_D(QPlainTextEdit); QTextOption opt = d->control->document()->defaultTextOption(); - if (opt.tabStop() == width || width < 0) + if (opt.tabStopDistance() == distance || distance < 0) return; - opt.setTabStop(width); + opt.setTabStopDistance(distance); d->control->document()->setDefaultTextOption(opt); } + /*! \property QPlainTextEdit::cursorWidth diff --git a/src/widgets/widgets/qplaintextedit.h b/src/widgets/widgets/qplaintextedit.h index 29d610a129..cd25b45d50 100644 --- a/src/widgets/widgets/qplaintextedit.h +++ b/src/widgets/widgets/qplaintextedit.h @@ -73,7 +73,10 @@ class Q_WIDGETS_EXPORT QPlainTextEdit : public QAbstractScrollArea Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) Q_PROPERTY(QString plainText READ toPlainText WRITE setPlainText NOTIFY textChanged USER true) Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode) +#if QT_DEPRECATED_SINCE(5, 10) Q_PROPERTY(int tabStopWidth READ tabStopWidth WRITE setTabStopWidth) +#endif + Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance) Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth) Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) Q_PROPERTY(int blockCount READ blockCount) @@ -167,8 +170,13 @@ public: bool overwriteMode() const; void setOverwriteMode(bool overwrite); - int tabStopWidth() const; - void setTabStopWidth(int width); +#if QT_DEPRECATED_SINCE(5, 10) + QT_DEPRECATED int tabStopWidth() const; + QT_DEPRECATED void setTabStopWidth(int width); +#endif + + qreal tabStopDistance() const; + void setTabStopDistance(qreal distance); int cursorWidth() const; void setCursorWidth(int width); diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp index c408a87339..91f7efa08c 100644 --- a/src/widgets/widgets/qprogressbar.cpp +++ b/src/widgets/widgets/qprogressbar.cpp @@ -213,7 +213,7 @@ bool QProgressBarPrivate::repaintRequired() const Note that whether or not the text is drawn is dependent on the style. Currently CleanLooks and Plastique draw the text. Mac, Windows - and WindowsXP style do not. + and WindowsVista style do not. \sa textDirection */ diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index 90b1e7ef29..caf175e6ff 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -40,6 +40,7 @@ #include "qapplication.h" #include "qbitmap.h" #include "qdesktopwidget.h" +#include <private/qdesktopwidget_p.h> #if QT_CONFIG(dialog) #include <private/qdialog_p.h> #endif @@ -58,10 +59,6 @@ #if QT_CONFIG(dialogbuttonbox) #include "qdialogbuttonbox.h" #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC -#include "private/qmacstyle_mac_p.h" -#include "private/qmacstyle_mac_p_p.h" -#endif #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" @@ -613,7 +610,7 @@ QPoint QPushButtonPrivate::adjustedMenuPosition() QPoint globalPos = q->mapToGlobal(rect.topLeft()); int x = globalPos.x(); int y = globalPos.y(); - const QRect availableGeometry = QApplication::desktop()->availableGeometry(q); + const QRect availableGeometry = QDesktopWidgetPrivate::availableGeometry(q); if (horizontal) { if (globalPos.y() + rect.height() + menuSize.height() <= availableGeometry.bottom()) { y += rect.height(); diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp index 1e1d847751..dc5a7158dd 100644 --- a/src/widgets/widgets/qsizegrip.cpp +++ b/src/widgets/widgets/qsizegrip.cpp @@ -55,6 +55,7 @@ #endif #include <private/qwidget_p.h> +#include <private/qdesktopwidget_p.h> #include <QtWidgets/qabstractscrollarea.h> QT_BEGIN_NAMESPACE @@ -312,7 +313,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) bool hasVerticalSizeConstraint = true; bool hasHorizontalSizeConstraint = true; if (tlw->isWindow()) - availableGeometry = QApplication::desktop()->availableGeometry(tlw); + availableGeometry = QDesktopWidgetPrivate::availableGeometry(tlw); else { const QWidget *tlwParent = tlw->parentWidget(); // Check if tlw is inside QAbstractScrollArea/QScrollArea. diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp index fb92d5de0d..468fc272b5 100644 --- a/src/widgets/widgets/qsplashscreen.cpp +++ b/src/widgets/widgets/qsplashscreen.cpp @@ -41,6 +41,7 @@ #include "qapplication.h" #include "qdesktopwidget.h" +#include <private/qdesktopwidget_p.h> #include "qpainter.h" #include "qpixmap.h" #include "qtextdocument.h" @@ -140,7 +141,7 @@ QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) one. In that case pass the proper desktop() as the \a parent. */ QSplashScreen::QSplashScreen(QWidget *parent, const QPixmap &pixmap, Qt::WindowFlags f) - : QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | f) + : QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | Qt::FramelessWindowHint | f) { d_func()->pixmap = pixmap; setPixmap(d_func()->pixmap); // Does an implicit repaint @@ -282,7 +283,7 @@ void QSplashScreen::setPixmap(const QPixmap &pixmap) QRect r(QPoint(), d->pixmap.size() / d->pixmap.devicePixelRatio()); resize(r.size()); - move(QApplication::desktop()->screenGeometry().center() - r.center()); + move(QDesktopWidgetPrivate::screenGeometry().center() - r.center()); if (isVisible()) repaint(); } diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h index 52e139c707..195ff79c5d 100644 --- a/src/widgets/widgets/qtabbar_p.h +++ b/src/widgets/widgets/qtabbar_p.h @@ -81,7 +81,7 @@ private: QPixmap m_pixmap; }; -class QTabBarPrivate : public QWidgetPrivate +class Q_WIDGETS_EXPORT QTabBarPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QTabBar) public: @@ -180,7 +180,7 @@ public: int indexAtPos(const QPoint &p) const; - inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animate, 0, q); } + inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, 0, q) > 0; } inline bool validIndex(int index) const { return index >= 0 && index < tabList.count(); } void setCurrentNextEnabledIndex(int offset); diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp index dc866a38cf..60a924510a 100644 --- a/src/widgets/widgets/qtabwidget.cpp +++ b/src/widgets/widgets/qtabwidget.cpp @@ -44,6 +44,7 @@ #include "qapplication.h" #include "qbitmap.h" #include "qdesktopwidget.h" +#include <private/qdesktopwidget_p.h> #include "qevent.h" #include "qlayout.h" #include "qstackedwidget.h" @@ -844,7 +845,7 @@ QSize QTabWidget::sizeHint() const if(usesScrollButtons()) t = t.boundedTo(QSize(200,200)); else - t = t.boundedTo(QApplication::desktop()->size()); + t = t.boundedTo(QDesktopWidgetPrivate::size()); QSize sz = basicSize(d->pos == North || d->pos == South, lc, rc, s, t); @@ -912,7 +913,7 @@ int QTabWidget::heightForWidth(int width) const if(usesScrollButtons()) t = t.boundedTo(QSize(200,200)); else - t = t.boundedTo(QApplication::desktop()->size()); + t = t.boundedTo(QDesktopWidgetPrivate::size()); const bool tabIsHorizontal = (d->pos == North || d->pos == South); const int contentsWidth = width - padding.width(); diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 374267f9f2..df8ecba112 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1955,27 +1955,48 @@ void QTextEdit::setOverwriteMode(bool overwrite) d->control->setOverwriteMode(overwrite); } +#if QT_DEPRECATED_SINCE(5, 10) /*! \property QTextEdit::tabStopWidth \brief the tab stop width in pixels \since 4.1 + \deprecated in Qt 5.10. Use tabStopDistance instead. By default, this property contains a value of 80 pixels. */ int QTextEdit::tabStopWidth() const { - Q_D(const QTextEdit); - return qRound(d->control->document()->defaultTextOption().tabStop()); + return qRound(tabStopDistance()); } void QTextEdit::setTabStopWidth(int width) { + setTabStopDistance(width); +} +#endif + +/*! + \property QTextEdit::tabStopDistance + \brief the tab stop distance in pixels + \since 5.10 + + By default, this property contains a value of 80 pixels. +*/ + +qreal QTextEdit::tabStopDistance() const +{ + Q_D(const QTextEdit); + return d->control->document()->defaultTextOption().tabStopDistance(); +} + +void QTextEdit::setTabStopDistance(qreal distance) +{ Q_D(QTextEdit); QTextOption opt = d->control->document()->defaultTextOption(); - if (opt.tabStop() == width || width < 0) + if (opt.tabStopDistance() == distance || distance < 0) return; - opt.setTabStop(width); + opt.setTabStopDistance(distance); d->control->document()->setDefaultTextOption(opt); } diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h index ff52fde2ed..954f0167ae 100644 --- a/src/widgets/widgets/qtextedit.h +++ b/src/widgets/widgets/qtextedit.h @@ -75,7 +75,10 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea #endif Q_PROPERTY(QString plainText READ toPlainText WRITE setPlainText DESIGNABLE false) Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode) +#if QT_DEPRECATED_SINCE(5, 10) Q_PROPERTY(int tabStopWidth READ tabStopWidth WRITE setTabStopWidth) +#endif + Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance) Q_PROPERTY(bool acceptRichText READ acceptRichText WRITE setAcceptRichText) Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth) Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) @@ -185,8 +188,13 @@ public: bool overwriteMode() const; void setOverwriteMode(bool overwrite); - int tabStopWidth() const; - void setTabStopWidth(int width); +#if QT_DEPRECATED_SINCE(5, 10) + QT_DEPRECATED int tabStopWidth() const; + QT_DEPRECATED void setTabStopWidth(int width); +#endif + + qreal tabStopDistance() const; + void setTabStopDistance(qreal distance); int cursorWidth() const; void setCursorWidth(int width); diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index 663e8214c0..1c6d41ee2f 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -92,7 +92,6 @@ void QToolBarPrivate::init() q->setBackgroundRole(QPalette::Button); q->setAttribute(Qt::WA_Hover); q->setAttribute(Qt::WA_X11NetWmWindowTypeToolBar); - q->setProperty("_q_platform_MacUseNSWindow", QVariant(true)); QStyle *style = q->style(); int e = style->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q); diff --git a/src/widgets/widgets/qtoolbar.h b/src/widgets/widgets/qtoolbar.h index e0f2d9b073..9ffb472c76 100644 --- a/src/widgets/widgets/qtoolbar.h +++ b/src/widgets/widgets/qtoolbar.h @@ -121,7 +121,7 @@ public: addAction(const QString &text, const Obj *object, Func1 slot) { QAction *result = addAction(text); - connect(result, &QAction::triggered, object, slot); + connect(result, &QAction::triggered, object, std::move(slot)); return result; } // addAction(QString): Connect to a functor or function pointer (without context) @@ -139,7 +139,7 @@ public: addAction(const QIcon &actionIcon, const QString &text, const Obj *object, Func1 slot) { QAction *result = addAction(actionIcon, text); - connect(result, &QAction::triggered, object, slot); + connect(result, &QAction::triggered, object, std::move(slot)); return result; } // addAction(QIcon, QString): Connect to a functor or function pointer (without context) diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index 58f1a296b2..96b88340cd 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -41,6 +41,7 @@ #include <qapplication.h> #include <qdesktopwidget.h> +#include <private/qdesktopwidget_p.h> #include <qdrawutil.h> #include <qevent.h> #include <qicon.h> @@ -749,7 +750,7 @@ void QToolButtonPrivate::popupTimerDone() #endif QPoint p; const QRect rect = q->rect(); // Find screen via point in case of QGraphicsProxyWidget. - QRect screen = QApplication::desktop()->availableGeometry(q->mapToGlobal(rect.center())); + QRect screen = QDesktopWidgetPrivate::availableGeometry(q->mapToGlobal(rect.center())); QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint(); if (horizontal) { if (q->isRightToLeft()) { diff --git a/src/widgets/widgets/qwidgetanimator.cpp b/src/widgets/widgets/qwidgetanimator.cpp index fdf2b5d321..b6828a14ef 100644 --- a/src/widgets/widgets/qwidgetanimator.cpp +++ b/src/widgets/widgets/qwidgetanimator.cpp @@ -93,13 +93,13 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo #ifndef QT_NO_ANIMATION //If the QStyle has animations, animate - if (widget->style()->styleHint(QStyle::SH_Widget_Animate, 0, widget)) { + if (const int animationDuration = widget->style()->styleHint(QStyle::SH_Widget_Animation_Duration, 0, widget)) { AnimationMap::const_iterator it = m_animation_map.constFind(widget); if (it != m_animation_map.constEnd() && (*it)->endValue().toRect() == final_geometry) return; QPropertyAnimation *anim = new QPropertyAnimation(widget, "geometry", widget); - anim->setDuration(animate ? 200 : 0); + anim->setDuration(animate ? animationDuration : 0); anim->setEasingCurve(QEasingCurve::InOutQuad); anim->setEndValue(final_geometry); m_animation_map[widget] = anim; diff --git a/src/widgets/widgets/qwidgetresizehandler.cpp b/src/widgets/widgets/qwidgetresizehandler.cpp index 5bd87ac91c..3612a04e99 100644 --- a/src/widgets/widgets/qwidgetresizehandler.cpp +++ b/src/widgets/widgets/qwidgetresizehandler.cpp @@ -42,6 +42,7 @@ #include "qframe.h" #include "qapplication.h" #include "qdesktopwidget.h" +#include <private/qdesktopwidget_p.h> #include "qcursor.h" #if QT_CONFIG(sizegrip) #include "qsizegrip.h" @@ -259,7 +260,7 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e) // Workaround for window managers which refuse to move a tool window partially offscreen. if (QGuiApplication::platformName() == QLatin1String("xcb")) { - const QRect desktop = QApplication::desktop()->availableGeometry(widget); + const QRect desktop = QDesktopWidgetPrivate::availableGeometry(widget); pp.rx() = qMax(pp.x(), desktop.left()); pp.ry() = qMax(pp.y(), desktop.top()); p.rx() = qMin(p.x(), desktop.right()); @@ -380,7 +381,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e) switch (e->key()) { case Qt::Key_Left: pos.rx() -= delta; - if (pos.x() <= QApplication::desktop()->geometry().left()) { + if (pos.x() <= QDesktopWidgetPrivate::geometry().left()) { if (mode == TopLeft || mode == BottomLeft) { moveOffset.rx() += delta; invertedMoveOffset.rx() += delta; @@ -405,7 +406,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e) break; case Qt::Key_Right: pos.rx() += delta; - if (pos.x() >= QApplication::desktop()->geometry().right()) { + if (pos.x() >= QDesktopWidgetPrivate::geometry().right()) { if (mode == TopRight || mode == BottomRight) { moveOffset.rx() += delta; invertedMoveOffset.rx() += delta; @@ -430,7 +431,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e) break; case Qt::Key_Up: pos.ry() -= delta; - if (pos.y() <= QApplication::desktop()->geometry().top()) { + if (pos.y() <= QDesktopWidgetPrivate::geometry().top()) { if (mode == TopLeft || mode == TopRight) { moveOffset.ry() += delta; invertedMoveOffset.ry() += delta; @@ -455,7 +456,7 @@ void QWidgetResizeHandler::keyPressEvent(QKeyEvent * e) break; case Qt::Key_Down: pos.ry() += delta; - if (pos.y() >= QApplication::desktop()->geometry().bottom()) { + if (pos.y() >= QDesktopWidgetPrivate::geometry().bottom()) { if (mode == BottomLeft || mode == BottomRight) { moveOffset.ry() += delta; invertedMoveOffset.ry() += delta; diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index da6dcfbe8b..aa5a3329e9 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -93,7 +93,10 @@ #include "private/qapplication_p.h" #include "private/qshortcutmap_p.h" #include <qkeysequence.h> -#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ +#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \ + ? false \ + : qApp->styleHints()->showShortcutsInContextMenus()) \ + && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \ QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString()) #else |