KDDockWidgets API Documentation 2.0
Loading...
Searching...
No Matches
qtwidgets/views/MainWindow.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
19#include "MainWindow.h"
20#include "Config.h"
22#include "ViewWrapper_p.h"
23#include "core/DockRegistry_p.h"
24#include "core/DropArea.h"
25#include "core/MainWindow.h"
26#include "core/MainWindow_p.h"
27#include "core/Group.h"
28#include "core/SideBar.h"
29#include "core/Window_p.h"
30#include "core/DockRegistry.h"
31
32#include "core/Logging_p.h"
33
34#include <QPainter>
35#include <QScreen>
36#include <QVBoxLayout>
37#include <QWindow>
38#include <QTimer>
39
40// clazy:excludeall=ctor-missing-parent-argument,missing-qobject-macro
41
42using namespace KDDockWidgets;
43using namespace KDDockWidgets::QtWidgets;
44
45namespace KDDockWidgets {
46
47char const *const s_centralWidgetObjectName = "MyCentralWidget";
48
49class MyCentralWidget : public QWidget
50{
51public:
52 explicit MyCentralWidget(QWidget *parent = nullptr)
54 {
56 }
57
58 ~MyCentralWidget() override;
59};
60}
61
62class MainWindow::Private
63{
64public:
65 explicit Private(MainWindow *qq)
66 : q(qq)
67 , m_controller(qq->mainWindow())
68 , m_supportsAutoHide(Config::self().flags() & Config::Flag_AutoHideSupport)
69 , m_centralWidget(new MyCentralWidget(qq))
70 , m_layout(new QHBoxLayout(m_centralWidget)) // 1 level of indirection so we can add some
71 // margins
72 {
73 }
74
75 ~Private()
76 {
77 }
78
79 void updateMargins()
80 {
81 const qreal factor = QtWidgets::logicalDpiFactor(q);
82 m_layout->setContentsMargins(m_centerWidgetMargins * factor);
83 }
84
85 void setupCentralLayout()
86 {
87 m_layout->setSpacing(0);
88 updateMargins();
89
90 if (m_supportsAutoHide) {
91 m_layout->addWidget(
92 View_qt::asQWidget(m_controller->sideBar(SideBarLocation::West)->view()));
93 auto innerVLayout = new QVBoxLayout();
94 innerVLayout->setSpacing(0);
95 innerVLayout->setContentsMargins(0, 0, 0, 0);
96 innerVLayout->addWidget(
97 View_qt::asQWidget(m_controller->sideBar(SideBarLocation::North)));
98 innerVLayout->addWidget(View_qt::asQWidget(m_controller->layout()));
99 innerVLayout->addWidget(
100 View_qt::asQWidget(m_controller->sideBar(SideBarLocation::South)));
101 m_layout->addLayout(innerVLayout);
102 m_layout->addWidget(View_qt::asQWidget(m_controller->sideBar(SideBarLocation::East)));
103 } else {
104 m_layout->addWidget(View_qt::asQWidget(m_controller->layout()->view()));
105 }
106
107 q->QMainWindow::setCentralWidget(m_centralWidget);
108 }
109
110 bool onlySupportsQDockWidgets() const
111 {
112 return m_controller && (m_controller->options() & MainWindowOption_QDockWidgets);
113 }
114
115 bool needsManualInit() const
116 {
117 return m_controller && (m_controller->options() & MainWindowOption_ManualInit);
118 }
119
121 void sanityCheckCentralWidget() const
122 {
123 if (auto cw = q->centralWidget()) {
124 if (cw->objectName() != QLatin1String(s_centralWidgetObjectName)) {
125 qWarning() << "MainWindow: Expected our own central widget, not " << cw->objectName();
126 }
127 }
128 }
129
130 MainWindow *const q;
131 Core::MainWindow *const m_controller;
132 const bool m_supportsAutoHide;
133 MyCentralWidget *const m_centralWidget;
134 QHBoxLayout *const m_layout;
135 QMargins m_centerWidgetMargins = { 1, 5, 1, 1 };
136
137 KDBindings::ScopedConnection groupCountChangedConnection;
138};
139
140MyCentralWidget::~MyCentralWidget() = default;
141
142MainWindow::MainWindow(const QString &uniqueName, MainWindowOptions options,
143 QWidget *parent, Qt::WindowFlags flags)
144 : View<QMainWindow>(new Core::MainWindow(this, uniqueName, options),
145 Core::ViewType::MainWindow, parent, flags)
146 , MainWindowViewInterface(static_cast<Core::MainWindow *>(controller()))
147 , d(new Private(this))
148{
149 if (options & MainWindowOption_QDockWidgets)
150 return;
151
152 // Disable QWidgetAnimator. We don't use QDockWidget, but QWidgetAnimator will appear in stack traces
153 // which is unneeded.
155
156 m_mainWindow->init(uniqueName);
157
158 const bool requiresManualInit = options & MainWindowOption_ManualInit;
159 if (!requiresManualInit)
160 d->setupCentralLayout();
161
162 const bool isWindow = !parentWidget() || (flags & Qt::Window);
163 if (isWindow) {
164 // Update our margins when logical dpi changes.
165 // QWidget doesn't have any screenChanged signal, so we need to use QWindow::screenChanged.
166 // Note #1: Someone might be using this main window embedded into another main window, in
167 // which case it will never have a QWindow, so guard it with isWindow. Note #2: We don't use
168 // QWidget::isWindow() as that will always be true since QMainWindow sets it. Anyone wanting
169 // or not wanting this immediate create() needs to pass a parent/flag pair that makes sense.
170 // For example, some people might want to add this main window into a layout and avoid the
171 // create(), so they pass a parent, with null flag.
172
173 create(); // ensure QWindow exists
174 window()->onScreenChanged(this, [](QObject *context, auto window) {
175 if (auto mw = qobject_cast<MainWindow *>(context))
176 mw->updateMargins(); // logical dpi might have changed
177 DockRegistry::self()->dptr()->windowChangedScreen.emit(window);
178 });
179 }
180
181 QTimer::singleShot(0, this, [this] {
182 d->sanityCheckCentralWidget();
183 });
184
185 d->groupCountChangedConnection = m_mainWindow->d->groupCountChanged.connect([this](int count) {
186 Q_EMIT groupCountChanged(count);
187 });
188}
189
191{
192 d->sanityCheckCentralWidget();
193 delete d;
194}
195
196void MainWindow::setCentralWidget(QWidget *w)
197{
199}
200
202{
203 return d->m_centerWidgetMargins;
204}
205
207{
208 if (d->m_centerWidgetMargins == margins)
209 return;
210 d->m_centerWidgetMargins = margins;
211 d->updateMargins();
212}
213
215{
216 return centralWidget()->geometry();
217}
218
219void MainWindow::setContentsMargins(int left, int top, int right, int bottom)
220{
221 QMainWindow::setContentsMargins(left, top, right, bottom);
222}
223
225{
226 m_mainWindow->setPersistentCentralView(QtWidgets::ViewWrapper::create(widget));
227}
228
230{
231 auto view = m_mainWindow->persistentCentralView();
232 return View_qt::asQWidget(view.get());
233}
234
236{
237 return d->m_layout;
238}
239
241{
242 d->updateMargins();
243}
244
246{
247 if (d->onlySupportsQDockWidgets()) {
249 } else {
250 qFatal("MainWindow::setCentralWidget_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
251 }
252}
253
255{
256 if (d->onlySupportsQDockWidgets()) {
257 QMainWindow::addDockWidget(area, dockwidget);
258 } else {
259 qFatal("MainWindow::addDockWidget_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
260 }
261}
262
264 Qt::Orientation orientation)
265{
266 if (d->onlySupportsQDockWidgets()) {
267 QMainWindow::addDockWidget(area, dockwidget, orientation);
268 } else {
269 qFatal("MainWindow::addDockWidget_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
270 }
271}
272
274{
275 if (d->onlySupportsQDockWidgets()) {
276 return QMainWindow::restoreDockWidget(dockwidget);
277 } else {
278 qFatal("MainWindow::restoreDockWidget_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
279 return {};
280 }
281}
282
284{
285 if (d->onlySupportsQDockWidgets()) {
287 } else {
288 qFatal("MainWindow::removeDockWidget_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
289 }
290}
291
293{
294 if (d->onlySupportsQDockWidgets()) {
295 return QMainWindow::dockWidgetArea(dockwidget);
296 } else {
297 qFatal("MainWindow::dockWidgetArea_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
298 return {};
299 }
300}
301
303 const QList<int> &sizes, Qt::Orientation orientation)
304{
305 if (d->onlySupportsQDockWidgets()) {
306 QMainWindow::resizeDocks(docks, sizes, orientation);
307 } else {
308 qFatal("MainWindow::resizeDocks_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
309 }
310}
311
313{
314 if (d->onlySupportsQDockWidgets()) {
315 QMainWindow::tabifyDockWidget(first, second);
316 } else {
317 qFatal("MainWindow::tabifyDockWidget_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
318 }
319}
320
322{
323 if (d->onlySupportsQDockWidgets()) {
324 return QMainWindow::tabifiedDockWidgets(dockwidget);
325 } else {
326 qFatal("MainWindow::tabifiedDockWidgets_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
327 return {};
328 }
329}
330
332 Qt::Orientation orientation)
333{
334 if (d->onlySupportsQDockWidgets()) {
335 QMainWindow::splitDockWidget(after, dockwidget, orientation);
336 } else {
337 qFatal("MainWindow::splitDockWidget_split_legacy: Legacy QDockWidgets are not supported without MainWindowOption_QDockWidgets");
338 }
339}
340
342{
343 if (d->needsManualInit()) {
344 delete centralWidget();
345 d->setupCentralLayout();
346 } else {
347 qFatal("MainWindow::manualInit requires MainWindowOption_ManualInit");
348 }
349}
Application-wide config to tune certain behaviours of the framework.
A ScopedConnection is a RAII-style way to make sure a Connection is disconnected.
Definition signal.h:533
Singleton to allow to choose certain behaviours of the framework.
Definition Config.h:64
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
std::shared_ptr< View > persistentCentralView() const
void setPersistentCentralView(std::shared_ptr< View > widget)
Sets a persistent central widget. It can't be detached.
static DockRegistry * self()
The QMainwindow sub-class that the application should use to be able to dock KDDockWidget DockWidget ...
Qt::DockWidgetArea dockWidgetArea_legacy(QDockWidget *dockwidget) const
bool restoreDockWidget_legacy(QDockWidget *dockwidget)
void addDockWidget_legacy(Qt::DockWidgetArea area, QDockWidget *dockwidget)
void tabifyDockWidget_legacy(QDockWidget *first, QDockWidget *second)
void setCentralWidget_legacy(QWidget *)
These *_legacy overloads provide QDockWidget compatibility, during porting. See MainWindowOption_QDoc...
void setPersistentCentralWidget(QWidget *widget)
QHBoxLayout * internalLayout() const
returns the internal layout this is rarely needed unless you want to layout other widgets next to the...
void setContentsMargins(int left, int top, int right, int bottom) override
Sets the main window's content margins.
~MainWindow() override
Destructor.
void resizeDocks_legacy(const QList< QDockWidget * > &docks, const QList< int > &sizes, Qt::Orientation orientation)
QWidget * persistentCentralWidget() const
void removeDockWidget_legacy(QDockWidget *dockwidget)
void setCenterWidgetMargins(QMargins)
sets the margins for the contents widget
QMargins centerWidgetMargins() const override
returns the margins for the contents widget
void updateMargins()
for internal use only
void splitDockWidget_split_legacy(QDockWidget *after, QDockWidget *dockwidget, Qt::Orientation orientation)
QRect centralAreaGeometry() const override
QList< QDockWidget * > tabifiedDockWidgets_legacy(QDockWidget *dockwidget) const
A MultiSplitter with support for drop indicators when hovering over.
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
ViewType
Each View type also has a specific Controller associated with, except for ViewType::None.
Definition Controller.h:26
qreal logicalDpiFactor(const QWidget *w)
Class to abstract QAction, so code still works with QtQuick and Flutter.
@ MainWindowOption_ManualInit
@ MainWindowOption_QDockWidgets
char const *const s_centralWidgetObjectName
void addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget)
QWidget * centralWidget() const const
void setDockOptions(QMainWindow::DockOptions options)
Qt::DockWidgetArea dockWidgetArea(QDockWidget *dockwidget) const const
void removeDockWidget(QDockWidget *dockwidget)
void resizeDocks(const QList< QDockWidget * > &docks, const QList< int > &sizes, Qt::Orientation orientation)
bool restoreDockWidget(QDockWidget *dockwidget)
void setCentralWidget(QWidget *widget)
void splitDockWidget(QDockWidget *first, QDockWidget *second, Qt::Orientation orientation)
QList< QDockWidget * > tabifiedDockWidgets(QDockWidget *dockwidget) const const
void tabifyDockWidget(QDockWidget *first, QDockWidget *second)
void setObjectName(const QString &name)
QObject * parent() const const
DockWidgetArea
Orientation
typedef WindowFlags
A factory class for allowing the user to customize some internal widgets.
QMainWindow sub-class to enable KDDockWidgets support.
void setContentsMargins(int left, int top, int right, int bottom)

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated by doxygen 1.9.8