source: trunk/tools/designer/src/designer/mainwindow.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 14.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt Designer of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "mainwindow.h"
43#include "qdesigner.h"
44#include "qdesigner_actions.h"
45#include "qdesigner_workbench.h"
46#include "qdesigner_formwindow.h"
47#include "qdesigner_toolwindow.h"
48#include "qdesigner_settings.h"
49#include "qttoolbardialog.h"
50
51#include <QtDesigner/QDesignerFormWindowInterface>
52
53#include <QtGui/QAction>
54#include <QtGui/QCloseEvent>
55#include <QtGui/QToolBar>
56#include <QtGui/QMdiSubWindow>
57#include <QtGui/QStatusBar>
58#include <QtGui/QMenu>
59#include <QtGui/QLayout>
60#include <QtGui/QDockWidget>
61
62#include <QtCore/QUrl>
63#include <QtCore/QDebug>
64
65static const char *uriListMimeFormatC = "text/uri-list";
66
67QT_BEGIN_NAMESPACE
68
69typedef QList<QAction *> ActionList;
70
71// Helpers for creating toolbars and menu
72
73static void addActionsToToolBar(const ActionList &actions, QToolBar *t)
74{
75 const ActionList::const_iterator cend = actions.constEnd();
76 for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) {
77 QAction *action = *it;
78 if (!action->icon().isNull())
79 t->addAction(action);
80 }
81}
82static QToolBar *createToolBar(const QString &title, const QString &objectName, const ActionList &actions)
83{
84 QToolBar *rc = new QToolBar;
85 rc->setObjectName(objectName);
86 rc->setWindowTitle(title);
87 addActionsToToolBar(actions, rc);
88 return rc;
89}
90
91// ---------------- MainWindowBase
92
93MainWindowBase::MainWindowBase(QWidget *parent, Qt::WindowFlags flags) :
94 QMainWindow(parent, flags),
95 m_policy(AcceptCloseEvents)
96{
97#if !defined(Q_WS_MAC) && !defined(Q_WS_PM)
98 setWindowIcon(qDesigner->windowIcon());
99#endif
100}
101
102void MainWindowBase::closeEvent(QCloseEvent *e)
103{
104 switch (m_policy) {
105 case AcceptCloseEvents:
106 QMainWindow::closeEvent(e);
107 break;
108 case EmitCloseEventSignal:
109 emit closeEventReceived(e);
110 break;
111 }
112}
113
114QList<QToolBar *> MainWindowBase::createToolBars(const QDesignerActions *actions, bool singleToolBar)
115{
116 QList<QToolBar *> rc;
117 if (singleToolBar) {
118 //: Not currently used (main tool bar)
119 QToolBar *main = createToolBar(tr("Main"), QLatin1String("mainToolBar"), actions->fileActions()->actions());
120 addActionsToToolBar(actions->editActions()->actions(), main);
121 addActionsToToolBar(actions->toolActions()->actions(), main);
122 addActionsToToolBar(actions->formActions()->actions(), main);
123 rc.push_back(main);
124 } else {
125 rc.push_back(createToolBar(tr("File"), QLatin1String("fileToolBar"), actions->fileActions()->actions()));
126 rc.push_back(createToolBar(tr("Edit"), QLatin1String("editToolBar"), actions->editActions()->actions()));
127 rc.push_back(createToolBar(tr("Tools"), QLatin1String("toolsToolBar"), actions->toolActions()->actions()));
128 rc.push_back(createToolBar(tr("Form"), QLatin1String("formToolBar"), actions->formActions()->actions()));
129 }
130 return rc;
131}
132
133QString MainWindowBase::mainWindowTitle()
134{
135 return tr("Qt Designer");
136}
137
138// Use the minor Qt version as settings versions to avoid conflicts
139int MainWindowBase::settingsVersion()
140{
141 const int version = QT_VERSION;
142 return (version & 0x00FF00) >> 8;
143}
144
145// ----------------- DockedMdiArea
146
147DockedMdiArea::DockedMdiArea(const QString &extension, QWidget *parent) :
148 QMdiArea(parent),
149 m_extension(extension)
150{
151 setAcceptDrops(true);
152 setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
153 setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
154}
155
156QStringList DockedMdiArea::uiFiles(const QMimeData *d) const
157{
158 // Extract dropped UI files from Mime data.
159 QStringList rc;
160 if (!d->hasFormat(QLatin1String(uriListMimeFormatC)))
161 return rc;
162 const QList<QUrl> urls = d->urls();
163 if (urls.empty())
164 return rc;
165 const QList<QUrl>::const_iterator cend = urls.constEnd();
166 for (QList<QUrl>::const_iterator it = urls.constBegin(); it != cend; ++it) {
167 const QString fileName = it->toLocalFile();
168 if (!fileName.isEmpty() && fileName.endsWith(m_extension))
169 rc.push_back(fileName);
170 }
171 return rc;
172}
173
174bool DockedMdiArea::event(QEvent *event)
175{
176 // Listen for desktop file manager drop and emit a signal once a file is
177 // dropped.
178 switch (event->type()) {
179#ifndef QT_NO_DRAGANDDROP
180 case QEvent::DragEnter: {
181 QDragEnterEvent *e = static_cast<QDragEnterEvent*>(event);
182 if (!uiFiles(e->mimeData()).empty()) {
183 e->acceptProposedAction();
184 return true;
185 }
186 }
187 break;
188 case QEvent::Drop: {
189 QDropEvent *e = static_cast<QDropEvent*>(event);
190 const QStringList files = uiFiles(e->mimeData());
191 const QStringList::const_iterator cend = files.constEnd();
192 for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) {
193 emit fileDropped(*it);
194 }
195 e->acceptProposedAction();
196 return true;
197 }
198 break;
199#endif
200 default:
201 break;
202 }
203 return QMdiArea::event(event);
204}
205
206// ------------- ToolBarManager:
207
208static void addActionsToToolBarManager(const ActionList &al, const QString &title, QtToolBarManager *tbm)
209{
210 const ActionList::const_iterator cend = al.constEnd();
211 for (ActionList::const_iterator it = al.constBegin(); it != cend; ++it)
212 tbm->addAction(*it, title);
213}
214
215ToolBarManager::ToolBarManager(QMainWindow *configureableMainWindow,
216 QWidget *parent,
217 QMenu *toolBarMenu,
218 const QDesignerActions *actions,
219 const QList<QToolBar *> &toolbars,
220 const QList<QDesignerToolWindow*> &toolWindows) :
221 QObject(parent),
222 m_configureableMainWindow(configureableMainWindow),
223 m_parent(parent),
224 m_toolBarMenu(toolBarMenu),
225 m_manager(new QtToolBarManager(this)),
226 m_configureAction(new QAction(tr("Configure Toolbars..."), this)),
227 m_toolbars(toolbars)
228{
229 m_configureAction->setMenuRole(QAction::NoRole);
230 m_configureAction->setObjectName(QLatin1String("__qt_configure_tool_bars_action"));
231 connect(m_configureAction, SIGNAL(triggered()), this, SLOT(configureToolBars()));
232
233 m_manager->setMainWindow(configureableMainWindow);
234
235 foreach(QToolBar *tb, m_toolbars) {
236 const QString title = tb->windowTitle();
237 m_manager->addToolBar(tb, title);
238 addActionsToToolBarManager(tb->actions(), title, m_manager);
239 }
240
241 addActionsToToolBarManager(actions->windowActions()->actions(), tr("Window"), m_manager);
242 addActionsToToolBarManager(actions->helpActions()->actions(), tr("Help"), m_manager);
243
244 // Filter out the device profile preview actions which have int data().
245 ActionList previewActions = actions->styleActions()->actions();
246 ActionList::iterator it = previewActions.begin();
247 for ( ; (*it)->isSeparator() || (*it)->data().type() == QVariant::Int; ++it) ;
248 previewActions.erase(previewActions.begin(), it);
249 addActionsToToolBarManager(previewActions, tr("Style"), m_manager);
250
251 const QString dockTitle = tr("Dock views");
252 foreach (QDesignerToolWindow *tw, toolWindows) {
253 if (QAction *action = tw->action())
254 m_manager->addAction(action, dockTitle);
255 }
256
257 m_manager->addAction(m_configureAction, tr("Toolbars"));
258 updateToolBarMenu();
259}
260
261// sort function for sorting tool bars alphabetically by title [non-static since called from template]
262
263bool toolBarTitleLessThan(const QToolBar *t1, const QToolBar *t2)
264{
265 return t1->windowTitle() < t2->windowTitle();
266}
267
268void ToolBarManager::updateToolBarMenu()
269{
270 // Sort tool bars alphabetically by title
271 qStableSort(m_toolbars.begin(), m_toolbars.end(), toolBarTitleLessThan);
272 // add to menu
273 m_toolBarMenu->clear();
274 foreach (QToolBar *tb, m_toolbars)
275 m_toolBarMenu->addAction(tb->toggleViewAction());
276 m_toolBarMenu->addAction(m_configureAction);
277}
278
279void ToolBarManager::configureToolBars()
280{
281 QtToolBarDialog dlg(m_parent);
282 dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint);
283 dlg.setToolBarManager(m_manager);
284 dlg.exec();
285 updateToolBarMenu();
286}
287
288QByteArray ToolBarManager::saveState(int version) const
289{
290 return m_manager->saveState(version);
291}
292
293bool ToolBarManager::restoreState(const QByteArray &state, int version)
294{
295 return m_manager->restoreState(state, version);
296}
297
298// ---------- DockedMainWindow
299
300DockedMainWindow::DockedMainWindow(QDesignerWorkbench *wb,
301 QMenu *toolBarMenu,
302 const QList<QDesignerToolWindow*> &toolWindows) :
303 m_toolBarManager(0)
304{
305 setObjectName(QLatin1String("MDIWindow"));
306 setWindowTitle(mainWindowTitle());
307
308 const QList<QToolBar *> toolbars = createToolBars(wb->actionManager(), false);
309 foreach (QToolBar *tb, toolbars)
310 addToolBar(tb);
311 DockedMdiArea *dma = new DockedMdiArea(wb->actionManager()->uiExtension());
312 connect(dma, SIGNAL(fileDropped(QString)),
313 this, SIGNAL(fileDropped(QString)));
314 connect(dma, SIGNAL(subWindowActivated(QMdiSubWindow*)),
315 this, SLOT(slotSubWindowActivated(QMdiSubWindow*)));
316 setCentralWidget(dma);
317
318 QStatusBar *sb = statusBar();
319 Q_UNUSED(sb)
320
321 m_toolBarManager = new ToolBarManager(this, this, toolBarMenu, wb->actionManager(), toolbars, toolWindows);
322}
323
324QMdiArea *DockedMainWindow::mdiArea() const
325{
326 return static_cast<QMdiArea *>(centralWidget());
327}
328
329void DockedMainWindow::slotSubWindowActivated(QMdiSubWindow* subWindow)
330{
331 if (subWindow) {
332 QWidget *widget = subWindow->widget();
333 if (QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow*>(widget)) {
334 emit formWindowActivated(fw);
335 mdiArea()->setActiveSubWindow(subWindow);
336 }
337 }
338}
339
340// Create a MDI subwindow for the form.
341QMdiSubWindow *DockedMainWindow::createMdiSubWindow(QWidget *fw, Qt::WindowFlags f, const QKeySequence &designerCloseActionShortCut)
342{
343 QMdiSubWindow *rc = mdiArea()->addSubWindow(fw, f);
344 // Make action shortcuts respond only if focused to avoid conflicts with
345 // designer menu actions
346 if (designerCloseActionShortCut == QKeySequence(QKeySequence::Close)) {
347 const ActionList systemMenuActions = rc->systemMenu()->actions();
348 if (!systemMenuActions.empty()) {
349 const ActionList::const_iterator cend = systemMenuActions.constEnd();
350 for (ActionList::const_iterator it = systemMenuActions.constBegin(); it != cend; ++it) {
351 if ( (*it)->shortcut() == designerCloseActionShortCut) {
352 (*it)->setShortcutContext(Qt::WidgetShortcut);
353 break;
354 }
355 }
356 }
357 }
358 return rc;
359}
360
361DockedMainWindow::DockWidgetList DockedMainWindow::addToolWindows(const DesignerToolWindowList &tls)
362{
363 DockWidgetList rc;
364 foreach (QDesignerToolWindow *tw, tls) {
365 QDockWidget *dockWidget = new QDockWidget;
366 dockWidget->setObjectName(tw->objectName() + QLatin1String("_dock"));
367 dockWidget->setWindowTitle(tw->windowTitle());
368 addDockWidget(tw->dockWidgetAreaHint(), dockWidget);
369 dockWidget->setWidget(tw);
370 rc.push_back(dockWidget);
371 }
372 return rc;
373}
374
375// Settings consist of MainWindow state and tool bar manager state
376void DockedMainWindow::restoreSettings(const QDesignerSettings &s, const DockWidgetList &dws, const QRect &desktopArea)
377{
378 const int version = settingsVersion();
379 m_toolBarManager->restoreState(s.toolBarsState(DockedMode), version);
380
381 // If there are no old geometry settings, show the window maximized
382 s.restoreGeometry(this, QRect(desktopArea.topLeft(), QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)));
383
384 const QByteArray mainWindowState = s.mainWindowState(DockedMode);
385 const bool restored = !mainWindowState.isEmpty() && restoreState(mainWindowState, version);
386 if (!restored) {
387 // Default: Tabify less relevant windows bottom/right.
388 tabifyDockWidget(dws.at(QDesignerToolWindow::SignalSlotEditor),
389 dws.at(QDesignerToolWindow::ActionEditor));
390 tabifyDockWidget(dws.at(QDesignerToolWindow::ActionEditor),
391 dws.at(QDesignerToolWindow::ResourceEditor));
392 }
393}
394
395void DockedMainWindow::saveSettings(QDesignerSettings &s) const
396{
397 const int version = settingsVersion();
398 s.setToolBarsState(DockedMode, m_toolBarManager->saveState(version));
399 s.saveGeometryFor(this);
400 s.setMainWindowState(DockedMode, saveState(version));
401}
402
403QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.