Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
mainwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "mainwindow.h"
5#include "qdesigner.h"
12
13#include <QtDesigner/abstractformwindow.h>
14
15#include <QtWidgets/qtoolbar.h>
16#include <QtWidgets/qmdisubwindow.h>
17#include <QtWidgets/qstatusbar.h>
18#include <QtWidgets/qmenu.h>
19#include <QtWidgets/qlayout.h>
20#include <QtWidgets/qdockwidget.h>
21
22#include <QtGui/qaction.h>
23#include <QtGui/qactiongroup.h>
24#include <QtGui/qevent.h>
25
26#include <QtCore/qurl.h>
27#include <QtCore/qdebug.h>
28#include <QtCore/qmimedata.h>
29
30#include <algorithm>
31
32QT_BEGIN_NAMESPACE
33
34using namespace Qt::StringLiterals;
35
36using ActionList = QList<QAction *>;
37
38// Helpers for creating toolbars and menu
39
40static void addActionsToToolBar(const ActionList &actions, QToolBar *t)
41{
42 for (QAction *action : actions) {
43 if (action->property(QDesignerActions::defaultToolbarPropertyName).toBool())
44 t->addAction(action);
45 }
46}
47
48static QToolBar *createToolBar(const QString &title, const QString &objectName,
49 const ActionList &actions)
50{
51 QToolBar *rc = new QToolBar;
52 rc->setObjectName(objectName);
53 rc->setWindowTitle(title);
54 addActionsToToolBar(actions, rc);
55 return rc;
56}
57
58// ---------------- MainWindowBase
59
60MainWindowBase::MainWindowBase(QWidget *parent, Qt::WindowFlags flags) :
61 QMainWindow(parent, flags)
62{
63#ifndef Q_OS_MACOS
64 setWindowIcon(qDesigner->windowIcon());
65#endif
66}
67
68void MainWindowBase::closeEvent(QCloseEvent *e)
69{
70 switch (m_policy) {
72 QMainWindow::closeEvent(e);
73 break;
75 emit closeEventReceived(e);
76 break;
77 }
78}
79
80QList<QToolBar *> MainWindowBase::createToolBars(const QDesignerActions *actions, bool singleToolBar)
81{
82 // Note that whenever you want to add a new tool bar here, you also have to update the default
83 // action groups added to the toolbar manager in the mainwindow constructor
84 QList<QToolBar *> rc;
85 if (singleToolBar) {
86 //: Not currently used (main tool bar)
87 QToolBar *main = createToolBar(tr("Main"), u"mainToolBar"_s,
88 actions->fileActions()->actions());
89 addActionsToToolBar(actions->editActions()->actions(), main);
90 addActionsToToolBar(actions->toolActions()->actions(), main);
91 addActionsToToolBar(actions->formActions()->actions(), main);
92 rc.push_back(main);
93 } else {
94 rc.append(createToolBar(tr("File"), u"fileToolBar"_s,
95 actions->fileActions()->actions()));
96 rc.append(createToolBar(tr("Edit"), u"editToolBar"_s,
97 actions->editActions()->actions()));
98 rc.append(createToolBar(tr("Tools"), u"toolsToolBar"_s,
99 actions->toolActions()->actions()));
100 rc.append(createToolBar(tr("Form"), u"formToolBar"_s,
101 actions->formActions()->actions()));
102 }
103 return rc;
104}
105
106QString MainWindowBase::mainWindowTitle()
107{
108 return tr("Qt Widgets Designer");
109}
110
111// Use the minor Qt version as settings versions to avoid conflicts
113{
114 const int version = QT_VERSION;
115 return (version & 0x00FF00) >> 8;
116}
117
118// ----------------- DockedMdiArea
119
120DockedMdiArea::DockedMdiArea(const QString &extension, QWidget *parent) :
121 QMdiArea(parent),
122 m_extension(extension)
123{
124 setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
125 setLineWidth(1);
126 setAcceptDrops(true);
127 setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
128 setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
129}
130
131QStringList DockedMdiArea::uiFiles(const QMimeData *d) const
132{
133 // Extract dropped UI files from Mime data.
134 QStringList rc;
135 if (!d->hasFormat("text/uri-list"_L1))
136 return rc;
137 const auto urls = d->urls();
138 if (urls.isEmpty())
139 return rc;
140 for (const auto &url : urls) {
141 const QString fileName = url.toLocalFile();
142 if (!fileName.isEmpty() && fileName.endsWith(m_extension))
143 rc.push_back(fileName);
144 }
145 return rc;
146}
147
148bool DockedMdiArea::event(QEvent *event)
149{
150 // Listen for desktop file manager drop and emit a signal once a file is
151 // dropped.
152 switch (event->type()) {
153 case QEvent::DragEnter: {
154 QDragEnterEvent *e = static_cast<QDragEnterEvent*>(event);
155 if (!uiFiles(e->mimeData()).isEmpty()) {
156 e->acceptProposedAction();
157 return true;
158 }
159 }
160 break;
161 case QEvent::Drop: {
162 QDropEvent *e = static_cast<QDropEvent*>(event);
163 const QStringList files = uiFiles(e->mimeData());
164 for (const auto &f : files)
165 emit fileDropped(f);
166 e->acceptProposedAction();
167 return true;
168 }
169 break;
170 default:
171 break;
172 }
173 return QMdiArea::event(event);
174}
175
176// ------------- ToolBarManager:
177
178static void addActionsToToolBarManager(const ActionList &al, const QString &title, QtToolBarManager *tbm)
179{
180 for (QAction *action : al)
181 tbm->addAction(action, title);
182}
183
184ToolBarManager::ToolBarManager(QMainWindow *configureableMainWindow,
185 QWidget *parent,
186 QMenu *toolBarMenu,
187 const QDesignerActions *actions,
188 const QList<QToolBar *> &toolbars,
189 const QList<QDesignerToolWindow *> &toolWindows) :
190 QObject(parent),
191 m_configureableMainWindow(configureableMainWindow),
192 m_parent(parent),
193 m_toolBarMenu(toolBarMenu),
194 m_manager(new QtToolBarManager(this)),
195 m_configureAction(new QAction(tr("Configure Toolbars..."), this)),
196 m_toolbars(toolbars)
197{
198 m_configureAction->setMenuRole(QAction::NoRole);
199 m_configureAction->setObjectName(u"__qt_configure_tool_bars_action"_s);
200 connect(m_configureAction, &QAction::triggered, this, &ToolBarManager::configureToolBars);
201
202 m_manager->setMainWindow(configureableMainWindow);
203
204 for (QToolBar *tb : std::as_const(m_toolbars)) {
205 const QString title = tb->windowTitle();
206 m_manager->addToolBar(tb, title);
207 addActionsToToolBarManager(tb->actions(), title, m_manager);
208 }
209
210 addActionsToToolBarManager(actions->windowActions()->actions(), tr("Window"), m_manager);
211 addActionsToToolBarManager(actions->helpActions()->actions(), tr("Help"), m_manager);
212
213 // Filter out the device profile preview actions which have int data().
214 ActionList previewActions = actions->styleActions()->actions();
215 auto it = previewActions.begin();
216 for ( ; (*it)->isSeparator() || (*it)->data().metaType().id() == QMetaType::Int; ++it) ;
217 previewActions.erase(previewActions.begin(), it);
218 addActionsToToolBarManager(previewActions, tr("Style"), m_manager);
219
220 const QString dockTitle = tr("Dock views");
221 for (QDesignerToolWindow *tw : toolWindows) {
222 if (QAction *action = tw->action())
223 m_manager->addAction(action, dockTitle);
224 }
225
226 addActionsToToolBarManager(actions->fileActions()->actions(), tr("File"), m_manager);
227 addActionsToToolBarManager(actions->editActions()->actions(), tr("Edit"), m_manager);
228 addActionsToToolBarManager(actions->toolActions()->actions(), tr("Tools"), m_manager);
229 addActionsToToolBarManager(actions->formActions()->actions(), tr("Form"), m_manager);
230
231 m_manager->addAction(m_configureAction, tr("Toolbars"));
232 updateToolBarMenu();
233}
234
235// sort function for sorting tool bars alphabetically by title [non-static since called from template]
236
237bool toolBarTitleLessThan(const QToolBar *t1, const QToolBar *t2)
238{
239 return t1->windowTitle() < t2->windowTitle();
240}
241
242void ToolBarManager::updateToolBarMenu()
243{
244 // Sort tool bars alphabetically by title
245 std::stable_sort(m_toolbars.begin(), m_toolbars.end(), toolBarTitleLessThan);
246 // add to menu
247 m_toolBarMenu->clear();
248 for (QToolBar *tb : std::as_const(m_toolbars))
249 m_toolBarMenu->addAction(tb->toggleViewAction());
250 m_toolBarMenu->addAction(m_configureAction);
251}
252
253void ToolBarManager::configureToolBars()
254{
255 QtToolBarDialog dlg(m_parent);
256 dlg.setToolBarManager(m_manager);
257 dlg.exec();
258 updateToolBarMenu();
259}
260
262{
263 return m_manager->saveState(version);
264}
265
266bool ToolBarManager::restoreState(const QByteArray &state, int version)
267{
268 return m_manager->restoreState(state, version);
269}
270
271// ---------- DockedMainWindow
272
274 QMenu *toolBarMenu,
275 const QList<QDesignerToolWindow *> &toolWindows)
276{
277 setObjectName(u"MDIWindow"_s);
278 setWindowTitle(mainWindowTitle());
279
280 const QList<QToolBar *> toolbars = createToolBars(wb->actionManager(), false);
281 for (QToolBar *tb : toolbars)
282 addToolBar(tb);
283 DockedMdiArea *dma = new DockedMdiArea(wb->actionManager()->uiExtension());
284 connect(dma, &DockedMdiArea::fileDropped,
285 this, &DockedMainWindow::fileDropped);
286 connect(dma, &QMdiArea::subWindowActivated,
287 this, &DockedMainWindow::slotSubWindowActivated);
288 setCentralWidget(dma);
289
290 QStatusBar *sb = statusBar();
291 Q_UNUSED(sb);
292
293 m_toolBarManager = new ToolBarManager(this, this, toolBarMenu, wb->actionManager(), toolbars, toolWindows);
294}
295
296QMdiArea *DockedMainWindow::mdiArea() const
297{
298 return static_cast<QMdiArea *>(centralWidget());
299}
300
301void DockedMainWindow::slotSubWindowActivated(QMdiSubWindow* subWindow)
302{
303 if (subWindow) {
304 QWidget *widget = subWindow->widget();
305 if (QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow*>(widget)) {
306 emit formWindowActivated(fw);
307 mdiArea()->setActiveSubWindow(subWindow);
308 }
309 }
310}
311
312// Create a MDI subwindow for the form.
313QMdiSubWindow *DockedMainWindow::createMdiSubWindow(QWidget *fw, Qt::WindowFlags f, const QKeySequence &designerCloseActionShortCut)
314{
315 QMdiSubWindow *rc = mdiArea()->addSubWindow(fw, f);
316 // Make action shortcuts respond only if focused to avoid conflicts with
317 // designer menu actions
318 if (designerCloseActionShortCut == QKeySequence(QKeySequence::Close)) {
319 const ActionList systemMenuActions = rc->systemMenu()->actions();
320 for (auto *a : systemMenuActions) {
321 if (a->shortcut() == designerCloseActionShortCut) {
322 a->setShortcutContext(Qt::WidgetShortcut);
323 break;
324 }
325 }
326 }
327 return rc;
328}
329
331{
332 DockWidgetList rc;
333 for (QDesignerToolWindow *tw : tls) {
334 QDockWidget *dockWidget = new QDockWidget;
335 dockWidget->setObjectName(tw->objectName() + "_dock"_L1);
336 dockWidget->setWindowTitle(tw->windowTitle());
337 addDockWidget(tw->dockWidgetAreaHint(), dockWidget);
338 dockWidget->setWidget(tw);
339 rc.push_back(dockWidget);
340 }
341 return rc;
342}
343
344// Settings consist of MainWindow state and tool bar manager state
345void DockedMainWindow::restoreSettings(const QDesignerSettings &s, const DockWidgetList &dws, const QRect &desktopArea)
346{
347 const int version = settingsVersion();
348 m_toolBarManager->restoreState(s.toolBarsState(DockedMode), version);
349
350 // If there are no old geometry settings, show the window maximized
351 s.restoreGeometry(this, QRect(desktopArea.topLeft(), QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)));
352
353 const QByteArray mainWindowState = s.mainWindowState(DockedMode);
354 const bool restored = !mainWindowState.isEmpty() && restoreState(mainWindowState, version);
355 if (!restored) {
356 // Default: Tabify less relevant windows bottom/right.
357 tabifyDockWidget(dws.at(QDesignerToolWindow::SignalSlotEditor),
359 tabifyDockWidget(dws.at(QDesignerToolWindow::ActionEditor),
361 }
362}
363
365{
366 const int version = settingsVersion();
367 s.setToolBarsState(DockedMode, m_toolBarManager->saveState(version));
368 s.saveGeometryFor(this);
369 s.setMainWindowState(DockedMode, saveState(version));
370}
371
372QT_END_NAMESPACE
DockedMainWindow(QDesignerWorkbench *wb, QMenu *toolBarMenu, const DesignerToolWindowList &toolWindows)
DockWidgetList addToolWindows(const DesignerToolWindowList &toolWindows)
void saveSettings(QDesignerSettings &) const
QMdiArea * mdiArea() const
bool event(QEvent *event) override
static int settingsVersion()
QActionGroup * helpActions() const
QActionGroup * fileActions() const
QActionGroup * editActions() const
QActionGroup * formActions() const
QActionGroup * toolActions() const
QActionGroup * windowActions() const
QByteArray toolBarsState(UIMode mode) const
void saveGeometryFor(const QWidget *w)
QDesignerActions * actionManager() const
friend class QWidget
Definition qpainter.h:421
The QtToolBarDialog class provides a dialog for customizing toolbars.
void setToolBarManager(QtToolBarManager *toolBarManager)
Connects the toolbar dialog to the given toolBarManager.
The QtToolBarManager class provides toolbar management for main windows.
QByteArray saveState(int version=0) const
Saves the state of the toolbar manager's toolbars.
bool restoreState(const QByteArray &state, int version=0)
Restores the saved state of the toolbar manager's toolbars.
void setMainWindow(QMainWindow *mainWindow)
Sets the main window upon which the toolbar manager operates, to be the given mainWindow.
QByteArray saveState(int version=0) const
bool restoreState(const QByteArray &state, int version=0)
@ DockedMode
#define qDesigner
Definition qdesigner.h:12
static void addActionsToToolBar(const ActionList &actions, QToolBar *t)
static void addActionsToToolBarManager(const ActionList &al, const QString &title, QtToolBarManager *tbm)
static QToolBar * createToolBar(const QString &title, const QString &objectName, const ActionList &actions)
bool toolBarTitleLessThan(const QToolBar *t1, const QToolBar *t2)