diff options
Diffstat (limited to 'src/widgets/widgets/qmainwindow.cpp')
-rw-r--r-- | src/widgets/widgets/qmainwindow.cpp | 201 |
1 files changed, 90 insertions, 111 deletions
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 411b482c11..4534058d45 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only //#define QT_EXPERIMENTAL_CLIENT_DECORATIONS @@ -61,40 +25,42 @@ #include <qstyle.h> #include <qdebug.h> #include <qpainter.h> +#include <qmimedata.h> #include <private/qwidget_p.h> #if QT_CONFIG(toolbar) #include "qtoolbar_p.h" #endif #include "qwidgetanimator_p.h" -#ifdef Q_OS_OSX -#include <qpa/qplatformnativeinterface.h> -#endif +#include <QtGui/qpa/qplatformwindow.h> +#include <QtGui/qpa/qplatformwindow_p.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + class QMainWindowPrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QMainWindow) public: inline QMainWindowPrivate() - : layout(0), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly) -#ifdef Q_OS_OSX + : layout(nullptr), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly) +#ifdef Q_OS_MACOS , useUnifiedToolBar(false) #endif { } - QMainWindowLayout *layout; + QPointer<QMainWindowLayout> layout; QSize iconSize; bool explicitIconSize; Qt::ToolButtonStyle toolButtonStyle; -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS bool useUnifiedToolBar; #endif void init(); static inline QMainWindowLayout *mainWindowLayout(const QMainWindow *mainWindow) { - return mainWindow ? mainWindow->d_func()->layout : static_cast<QMainWindowLayout *>(0); + return mainWindow ? mainWindow->d_func()->layout.data() : static_cast<QMainWindowLayout *>(nullptr); } }; @@ -152,12 +118,13 @@ void QMainWindowPrivate::init() topLayout->addItem(layout, 1, 1); #else - layout = new QMainWindowLayout(q, 0); + layout = new QMainWindowLayout(q, nullptr); #endif - const int metric = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q); + const int metric = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, nullptr, q); iconSize = QSize(metric, metric); q->setAttribute(Qt::WA_Hover); + q->setAcceptDrops(true); } /* @@ -214,9 +181,6 @@ void QMainWindowPrivate::init() \image mainwindowlayout.png - \note Creating a main window without a central widget is not supported. - You must have a central widget even if it is just a placeholder. - \section1 Creating Main Window Components A central widget will typically be a standard Qt widget such @@ -316,9 +280,7 @@ void QMainWindowPrivate::init() is the position and size (relative to the size of the main window) of the toolbars and dock widgets that are stored. - \sa QMenuBar, QToolBar, QStatusBar, QDockWidget, {Application - Example}, {Dock Widgets Example}, {MDI Example}, {SDI Example}, - {Menus Example} + \sa QMenuBar, QToolBar, QStatusBar, QDockWidget, {Menus Example} */ /*! @@ -452,7 +414,7 @@ void QMainWindow::setIconSize(const QSize &iconSize) Q_D(QMainWindow); QSize sz = iconSize; if (!sz.isValid()) { - const int metric = style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, this); + const int metric = style()->pixelMetric(QStyle::PM_ToolBarIconSize, nullptr, this); sz = QSize(metric, metric); } if (d->iconSize != sz) { @@ -523,10 +485,10 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar) { QLayout *topLayout = layout(); - if (topLayout->menuBar() && topLayout->menuBar() != menuBar) { + if (QWidget *existingMenuBar = topLayout->menuBar(); existingMenuBar && existingMenuBar != menuBar) { // Reparent corner widgets before we delete the old menu bar. - QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(topLayout->menuBar()); - if (menuBar) { + QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(existingMenuBar); + if (oldMenuBar && menuBar) { // TopLeftCorner widget. QWidget *cornerWidget = oldMenuBar->cornerWidget(Qt::TopLeftCorner); if (cornerWidget) @@ -536,9 +498,10 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar) if (cornerWidget) menuBar->setCornerWidget(cornerWidget, Qt::TopRightCorner); } - oldMenuBar->hide(); - oldMenuBar->setParent(nullptr); - oldMenuBar->deleteLater(); + + existingMenuBar->hide(); + existingMenuBar->setParent(nullptr); + existingMenuBar->deleteLater(); } topLayout->setMenuBar(menuBar); } @@ -596,7 +559,7 @@ QStatusBar *QMainWindow::statusBar() const /*! Sets the status bar for the main window to \a statusbar. - Setting the status bar to 0 will remove it from the main window. + Setting the status bar to \nullptr will remove it from the main window. Note that QMainWindow takes ownership of the \a statusbar pointer and deletes it at the appropriate time. @@ -615,7 +578,7 @@ void QMainWindow::setStatusBar(QStatusBar *statusbar) /*! Returns the central widget for the main window. This function - returns zero if the central widget has not been set. + returns \nullptr if the central widget has not been set. \sa setCentralWidget() */ @@ -652,8 +615,8 @@ QWidget *QMainWindow::takeCentralWidget() Q_D(QMainWindow); QWidget *oldcentralwidget = d->layout->centralWidget(); if (oldcentralwidget) { - oldcentralwidget->setParent(0); - d->layout->setCentralWidget(0); + oldcentralwidget->setParent(nullptr); + d->layout->setCentralWidget(nullptr); } return oldcentralwidget; } @@ -762,7 +725,7 @@ void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar) disconnect(this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)), toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle))); - if(toolbar->d_func()->state && toolbar->d_func()->state->dragging) { + if (toolbar->d_func()->state && toolbar->d_func()->state->dragging) { //removing a toolbar which is dragging will cause crash #if QT_CONFIG(dockwidget) bool animated = isAnimated(); @@ -851,7 +814,7 @@ void QMainWindow::removeToolBar(QToolBar *toolbar) \sa addToolBar(), addToolBarBreak(), Qt::ToolBarArea */ -Qt::ToolBarArea QMainWindow::toolBarArea(QToolBar *toolbar) const +Qt::ToolBarArea QMainWindow::toolBarArea(const QToolBar *toolbar) const { return d_func()->layout->toolBarArea(toolbar); } /*! @@ -950,10 +913,10 @@ void QMainWindow::setDockNestingEnabled(bool enabled) \since 4.2 If this property is set to false, dock areas containing tabbed dock widgets - display horizontal tabs, simmilar to Visual Studio. + display horizontal tabs, similar to Visual Studio. If this property is set to true, then the right and left dock areas display vertical - tabs, simmilar to KDevelop. + tabs, similar to KDevelop. This property should be set before any dock widgets are added to the main window. */ @@ -1134,6 +1097,7 @@ void QMainWindow::splitDockWidget(QDockWidget *after, QDockWidget *dockwidget, d_func()->layout->splitDockWidget(after, dockwidget, orientation); } +#if QT_CONFIG(tabbar) /*! \fn void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second) @@ -1159,26 +1123,10 @@ void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second) QList<QDockWidget*> QMainWindow::tabifiedDockWidgets(QDockWidget *dockwidget) const { - QList<QDockWidget*> ret; -#if !QT_CONFIG(tabbar) - Q_UNUSED(dockwidget); -#else - const QDockAreaLayoutInfo *info = d_func()->layout->layoutState.dockAreaLayout.info(dockwidget); - if (info && info->tabbed && info->tabBar) { - for(int i = 0; i < info->item_list.count(); ++i) { - const QDockAreaLayoutItem &item = info->item_list.at(i); - if (item.widgetItem) { - if (QDockWidget *dock = qobject_cast<QDockWidget*>(item.widgetItem->widget())) { - if (dock != dockwidget) { - ret += dock; - } - } - } - } - } -#endif - return ret; + Q_D(const QMainWindow); + return d->layout ? d->layout->tabifiedDockWidgets(dockwidget) : QList<QDockWidget *>(); } +#endif // QT_CONFIG(tabbar) /*! @@ -1221,7 +1169,7 @@ Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const resized such that the yellowWidget is twice as big as the blueWidget If some widgets are grouped in tabs, only one widget per group should be - specified. Widgets not in the list might be changed to repect the constraints. + specified. Widgets not in the list might be changed to respect the constraints. */ void QMainWindow::resizeDocks(const QList<QDockWidget *> &docks, const QList<int> &sizes, Qt::Orientation orientation) @@ -1258,6 +1206,7 @@ QByteArray QMainWindow::saveState(int version) const { QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); + stream.setVersion(QDataStream::Qt_5_0); stream << QMainWindowLayout::VersionMarker; stream << version; d_func()->layout->saveState(stream); @@ -1286,6 +1235,7 @@ bool QMainWindow::restoreState(const QByteArray &state, int version) return false; QByteArray sd = state; QDataStream stream(&sd, QIODevice::ReadOnly); + stream.setVersion(QDataStream::Qt_5_0); int marker, v; stream >> marker; stream >> v; @@ -1309,6 +1259,7 @@ bool QMainWindow::event(QEvent *event) #if QT_CONFIG(toolbar) case QEvent::ToolBarChange: { + Q_ASSERT(d->layout); d->layout->toggleToolBarsVisible(); return true; } @@ -1317,6 +1268,7 @@ bool QMainWindow::event(QEvent *event) #if QT_CONFIG(statustip) case QEvent::StatusTip: #if QT_CONFIG(statusbar) + Q_ASSERT(d->layout); if (QStatusBar *sb = d->layout->statusBar()) sb->showMessage(static_cast<QStatusTipEvent*>(event)->tip()); else @@ -1327,11 +1279,34 @@ bool QMainWindow::event(QEvent *event) case QEvent::StyleChange: #if QT_CONFIG(dockwidget) + Q_ASSERT(d->layout); d->layout->layoutState.dockAreaLayout.styleChangedEvent(); #endif if (!d->explicitIconSize) setIconSize(QSize()); break; +#if QT_CONFIG(draganddrop) + case QEvent::DragEnter: + case QEvent::Drop: + if (!d->layout->draggingWidget) + break; + event->accept(); + return true; + case QEvent::DragMove: { + if (!d->layout->draggingWidget) + break; + auto dragMoveEvent = static_cast<QDragMoveEvent *>(event); + d->layout->hover(d->layout->draggingWidget, + mapToGlobal(dragMoveEvent->position()).toPoint()); + event->accept(); + return true; + } + case QEvent::DragLeave: + if (!d->layout->draggingWidget) + break; + d->layout->hover(d->layout->draggingWidget, pos() - QPoint(-1, -1)); + return true; +#endif default: break; } @@ -1347,38 +1322,42 @@ bool QMainWindow::event(QEvent *event) Note that the Qt 5 implementation has several limitations compared to Qt 4: \list - \li Use in windows with OpenGL content is not supported. This includes QGLWidget and QOpenGLWidget. + \li Use in windows with OpenGL content is not supported. This includes QOpenGLWidget. \li Using dockable or movable toolbars may result in painting errors and is not recommended \endlist \since 5.2 */ -void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) +void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool enabled) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS + if (!isWindow()) + return; + Q_D(QMainWindow); - if (isWindow()) { - d->useUnifiedToolBar = set; - createWinId(); - - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - QPlatformNativeInterface::NativeResourceForIntegrationFunction function = - nativeInterface->nativeResourceFunctionForIntegration("setContentBorderEnabled"); - if (!function) - return; // Not Cocoa platform plugin. - - typedef void (*SetContentBorderEnabledFunction)(QWindow *window, bool enable); - (reinterpret_cast<SetContentBorderEnabledFunction>(function))(window()->windowHandle(), set); - update(); - } + d->useUnifiedToolBar = enabled; + + // The unified toolbar is drawn by the macOS style with a transparent background. + // To ensure a suitable surface format is used we need to first create backing + // QWindow so we have something to update the surface format on, and then let + // QWidget know about the translucency, which it will propagate to the surface. + setAttribute(Qt::WA_NativeWindow); + setAttribute(Qt::WA_TranslucentBackground, enabled); + + d->create(); // Create first, before querying the platform window + using namespace QNativeInterface::Private; + if (auto *platformWindow = dynamic_cast<QCocoaWindow*>(window()->windowHandle()->handle())) + platformWindow->setContentBorderEnabled(enabled); + + update(); #else - Q_UNUSED(set) + Q_UNUSED(enabled); #endif } bool QMainWindow::unifiedTitleAndToolBarOnMac() const { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS return d_func()->useUnifiedToolBar; #endif return false; @@ -1460,8 +1439,8 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event) #if QT_CONFIG(menu) /*! Returns a popup menu containing checkable entries for the toolbars and - dock widgets present in the main window. If there are no toolbars and - dock widgets present, this function returns a null pointer. + dock widgets present in the main window. If there are no toolbars and + dock widgets present, this function returns \nullptr. By default, this function is called by the main window when the user activates a context menu, typically by right-clicking on a toolbar or a dock @@ -1476,7 +1455,7 @@ void QMainWindow::contextMenuEvent(QContextMenuEvent *event) QMenu *QMainWindow::createPopupMenu() { Q_D(QMainWindow); - QMenu *menu = 0; + QMenu *menu = nullptr; #if QT_CONFIG(dockwidget) QList<QDockWidget *> dockwidgets = findChildren<QDockWidget *>(); if (dockwidgets.size()) { |