/**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the Qt Designer of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "qdesigner.h" #include "qdesigner_actions.h" #include "qdesigner_workbench.h" #include "qdesigner_formwindow.h" #include "qdesigner_toolwindow.h" #include "qdesigner_settings.h" #include "qttoolbardialog.h" #include #include #include #include #include #include #include #include #include #include #include static const char *uriListMimeFormatC = "text/uri-list"; QT_BEGIN_NAMESPACE typedef QList ActionList; // Helpers for creating toolbars and menu static void addActionsToToolBar(const ActionList &actions, QToolBar *t) { const ActionList::const_iterator cend = actions.constEnd(); for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it) { QAction *action = *it; if (action->property(QDesignerActions::defaultToolbarPropertyName).toBool()) t->addAction(action); } } static QToolBar *createToolBar(const QString &title, const QString &objectName, const ActionList &actions) { QToolBar *rc = new QToolBar; rc->setObjectName(objectName); rc->setWindowTitle(title); addActionsToToolBar(actions, rc); return rc; } // ---------------- MainWindowBase MainWindowBase::MainWindowBase(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags), m_policy(AcceptCloseEvents) { #ifndef Q_WS_MAC setWindowIcon(qDesigner->windowIcon()); #endif } void MainWindowBase::closeEvent(QCloseEvent *e) { switch (m_policy) { case AcceptCloseEvents: QMainWindow::closeEvent(e); break; case EmitCloseEventSignal: emit closeEventReceived(e); break; } } QList MainWindowBase::createToolBars(const QDesignerActions *actions, bool singleToolBar) { // Note that whenever you want to add a new tool bar here, you also have to update the default // action groups added to the toolbar manager in the mainwindow constructor QList rc; if (singleToolBar) { //: Not currently used (main tool bar) QToolBar *main = createToolBar(tr("Main"), QLatin1String("mainToolBar"), actions->fileActions()->actions()); addActionsToToolBar(actions->editActions()->actions(), main); addActionsToToolBar(actions->toolActions()->actions(), main); addActionsToToolBar(actions->formActions()->actions(), main); rc.push_back(main); } else { rc.push_back(createToolBar(tr("File"), QLatin1String("fileToolBar"), actions->fileActions()->actions())); rc.push_back(createToolBar(tr("Edit"), QLatin1String("editToolBar"), actions->editActions()->actions())); rc.push_back(createToolBar(tr("Tools"), QLatin1String("toolsToolBar"), actions->toolActions()->actions())); rc.push_back(createToolBar(tr("Form"), QLatin1String("formToolBar"), actions->formActions()->actions())); } return rc; } QString MainWindowBase::mainWindowTitle() { return tr("Qt Designer"); } // Use the minor Qt version as settings versions to avoid conflicts int MainWindowBase::settingsVersion() { const int version = QT_VERSION; return (version & 0x00FF00) >> 8; } // ----------------- DockedMdiArea DockedMdiArea::DockedMdiArea(const QString &extension, QWidget *parent) : QMdiArea(parent), m_extension(extension) { setAcceptDrops(true); setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); } QStringList DockedMdiArea::uiFiles(const QMimeData *d) const { // Extract dropped UI files from Mime data. QStringList rc; if (!d->hasFormat(QLatin1String(uriListMimeFormatC))) return rc; const QList urls = d->urls(); if (urls.empty()) return rc; const QList::const_iterator cend = urls.constEnd(); for (QList::const_iterator it = urls.constBegin(); it != cend; ++it) { const QString fileName = it->toLocalFile(); if (!fileName.isEmpty() && fileName.endsWith(m_extension)) rc.push_back(fileName); } return rc; } bool DockedMdiArea::event(QEvent *event) { // Listen for desktop file manager drop and emit a signal once a file is // dropped. switch (event->type()) { case QEvent::DragEnter: { QDragEnterEvent *e = static_cast(event); if (!uiFiles(e->mimeData()).empty()) { e->acceptProposedAction(); return true; } } break; case QEvent::Drop: { QDropEvent *e = static_cast(event); const QStringList files = uiFiles(e->mimeData()); const QStringList::const_iterator cend = files.constEnd(); for (QStringList::const_iterator it = files.constBegin(); it != cend; ++it) { emit fileDropped(*it); } e->acceptProposedAction(); return true; } break; default: break; } return QMdiArea::event(event); } // ------------- ToolBarManager: static void addActionsToToolBarManager(const ActionList &al, const QString &title, QtToolBarManager *tbm) { const ActionList::const_iterator cend = al.constEnd(); for (ActionList::const_iterator it = al.constBegin(); it != cend; ++it) tbm->addAction(*it, title); } ToolBarManager::ToolBarManager(QMainWindow *configureableMainWindow, QWidget *parent, QMenu *toolBarMenu, const QDesignerActions *actions, const QList &toolbars, const QList &toolWindows) : QObject(parent), m_configureableMainWindow(configureableMainWindow), m_parent(parent), m_toolBarMenu(toolBarMenu), m_manager(new QtToolBarManager(this)), m_configureAction(new QAction(tr("Configure Toolbars..."), this)), m_toolbars(toolbars) { m_configureAction->setMenuRole(QAction::NoRole); m_configureAction->setObjectName(QLatin1String("__qt_configure_tool_bars_action")); connect(m_configureAction, SIGNAL(triggered()), this, SLOT(configureToolBars())); m_manager->setMainWindow(configureableMainWindow); foreach(QToolBar *tb, m_toolbars) { const QString title = tb->windowTitle(); m_manager->addToolBar(tb, title); addActionsToToolBarManager(tb->actions(), title, m_manager); } addActionsToToolBarManager(actions->windowActions()->actions(), tr("Window"), m_manager); addActionsToToolBarManager(actions->helpActions()->actions(), tr("Help"), m_manager); // Filter out the device profile preview actions which have int data(). ActionList previewActions = actions->styleActions()->actions(); ActionList::iterator it = previewActions.begin(); for ( ; (*it)->isSeparator() || (*it)->data().type() == QVariant::Int; ++it) ; previewActions.erase(previewActions.begin(), it); addActionsToToolBarManager(previewActions, tr("Style"), m_manager); const QString dockTitle = tr("Dock views"); foreach (QDesignerToolWindow *tw, toolWindows) { if (QAction *action = tw->action()) m_manager->addAction(action, dockTitle); } QString category(tr("File")); foreach(QAction *action, actions->fileActions()->actions()) m_manager->addAction(action, category); category = tr("Edit"); foreach(QAction *action, actions->editActions()->actions()) m_manager->addAction(action, category); category = tr("Tools"); foreach(QAction *action, actions->toolActions()->actions()) m_manager->addAction(action, category); category = tr("Form"); foreach(QAction *action, actions->formActions()->actions()) m_manager->addAction(action, category); m_manager->addAction(m_configureAction, tr("Toolbars")); updateToolBarMenu(); } // sort function for sorting tool bars alphabetically by title [non-static since called from template] bool toolBarTitleLessThan(const QToolBar *t1, const QToolBar *t2) { return t1->windowTitle() < t2->windowTitle(); } void ToolBarManager::updateToolBarMenu() { // Sort tool bars alphabetically by title qStableSort(m_toolbars.begin(), m_toolbars.end(), toolBarTitleLessThan); // add to menu m_toolBarMenu->clear(); foreach (QToolBar *tb, m_toolbars) m_toolBarMenu->addAction(tb->toggleViewAction()); m_toolBarMenu->addAction(m_configureAction); } void ToolBarManager::configureToolBars() { // QtToolBarDialog dlg(m_parent); // dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowContextHelpButtonHint); // dlg.setToolBarManager(m_manager); // dlg.exec(); // updateToolBarMenu(); } QByteArray ToolBarManager::saveState(int version) const { return m_manager->saveState(version); } bool ToolBarManager::restoreState(const QByteArray &state, int version) { return m_manager->restoreState(state, version); } // ---------- DockedMainWindow DockedMainWindow::DockedMainWindow(QDesignerWorkbench *wb, QMenu *toolBarMenu, const QList &toolWindows) : m_toolBarManager(0) { setObjectName(QLatin1String("MDIWindow")); setWindowTitle(mainWindowTitle()); const QList toolbars = createToolBars(wb->actionManager(), false); foreach (QToolBar *tb, toolbars) addToolBar(tb); DockedMdiArea *dma = new DockedMdiArea(wb->actionManager()->uiExtension()); connect(dma, SIGNAL(fileDropped(QString)), this, SIGNAL(fileDropped(QString))); connect(dma, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(slotSubWindowActivated(QMdiSubWindow*))); setCentralWidget(dma); QStatusBar *sb = statusBar(); Q_UNUSED(sb) m_toolBarManager = new ToolBarManager(this, this, toolBarMenu, wb->actionManager(), toolbars, toolWindows); } QMdiArea *DockedMainWindow::mdiArea() const { return static_cast(centralWidget()); } void DockedMainWindow::slotSubWindowActivated(QMdiSubWindow* subWindow) { if (subWindow) { QWidget *widget = subWindow->widget(); if (QDesignerFormWindow *fw = qobject_cast(widget)) { emit formWindowActivated(fw); mdiArea()->setActiveSubWindow(subWindow); } } } // Create a MDI subwindow for the form. QMdiSubWindow *DockedMainWindow::createMdiSubWindow(QWidget *fw, Qt::WindowFlags f, const QKeySequence &designerCloseActionShortCut) { QMdiSubWindow *rc = mdiArea()->addSubWindow(fw, f); // Make action shortcuts respond only if focused to avoid conflicts with // designer menu actions if (designerCloseActionShortCut == QKeySequence(QKeySequence::Close)) { const ActionList systemMenuActions = rc->systemMenu()->actions(); if (!systemMenuActions.empty()) { const ActionList::const_iterator cend = systemMenuActions.constEnd(); for (ActionList::const_iterator it = systemMenuActions.constBegin(); it != cend; ++it) { if ( (*it)->shortcut() == designerCloseActionShortCut) { (*it)->setShortcutContext(Qt::WidgetShortcut); break; } } } } return rc; } DockedMainWindow::DockWidgetList DockedMainWindow::addToolWindows(const DesignerToolWindowList &tls) { DockWidgetList rc; foreach (QDesignerToolWindow *tw, tls) { QDockWidget *dockWidget = new QDockWidget; dockWidget->setObjectName(tw->objectName() + QLatin1String("_dock")); dockWidget->setWindowTitle(tw->windowTitle()); addDockWidget(tw->dockWidgetAreaHint(), dockWidget); dockWidget->setWidget(tw); rc.push_back(dockWidget); } return rc; } // Settings consist of MainWindow state and tool bar manager state void DockedMainWindow::restoreSettings(const QDesignerSettings &s, const DockWidgetList &dws, const QRect &desktopArea) { const int version = settingsVersion(); m_toolBarManager->restoreState(s.toolBarsState(DockedMode), version); // If there are no old geometry settings, show the window maximized s.restoreGeometry(this, QRect(desktopArea.topLeft(), QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX))); const QByteArray mainWindowState = s.mainWindowState(DockedMode); const bool restored = !mainWindowState.isEmpty() && restoreState(mainWindowState, version); if (!restored) { // Default: Tabify less relevant windows bottom/right. tabifyDockWidget(dws.at(QDesignerToolWindow::SignalSlotEditor), dws.at(QDesignerToolWindow::ActionEditor)); tabifyDockWidget(dws.at(QDesignerToolWindow::ActionEditor), dws.at(QDesignerToolWindow::ResourceEditor)); } } void DockedMainWindow::saveSettings(QDesignerSettings &s) const { const int version = settingsVersion(); s.setToolBarsState(DockedMode, m_toolBarManager->saveState(version)); s.saveGeometryFor(this); s.setMainWindowState(DockedMode, saveState(version)); } QT_END_NAMESPACE