1099 lines
37 KiB
C++
1099 lines
37 KiB
C++
/****************************************************************************
|
|
**
|
|
** 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 "qdesigner_workbench.h"
|
|
#include "qdesigner.h"
|
|
#include "qdesigner_actions.h"
|
|
#include "qdesigner_appearanceoptions.h"
|
|
#include "qdesigner_settings.h"
|
|
#include "qdesigner_toolwindow.h"
|
|
#include "qdesigner_formwindow.h"
|
|
#include "appfontdialog.h"
|
|
|
|
#include <QtDesigner/QDesignerFormEditorInterface>
|
|
#include <QtDesigner/QDesignerFormWindowInterface>
|
|
#include <QtDesigner/QDesignerFormWindowManagerInterface>
|
|
#include <QtDesigner/QDesignerFormEditorPluginInterface>
|
|
#include <QtDesigner/QDesignerWidgetBoxInterface>
|
|
#include <QtDesigner/QDesignerMetaDataBaseInterface>
|
|
|
|
#include <QtDesigner/QDesignerComponents>
|
|
#include <QtDesigner/private/qdesigner_integration_p.h>
|
|
#include <QtDesigner/private/pluginmanager_p.h>
|
|
#include <QtDesigner/private/formwindowbase_p.h>
|
|
#include <QtDesigner/private/actioneditor_p.h>
|
|
|
|
#include <QtCore/QDir>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QUrl>
|
|
#include <QtCore/QTimer>
|
|
#include <QtCore/QPluginLoader>
|
|
#include <QtCore/qdebug.h>
|
|
|
|
#include <QtGui/QActionGroup>
|
|
#include <QtGui/QCloseEvent>
|
|
#include <QtGui/QDesktopWidget>
|
|
#include <QtGui/QDockWidget>
|
|
#include <QtGui/QMenu>
|
|
#include <QtGui/QMenuBar>
|
|
#include <QtGui/QMessageBox>
|
|
#include <QtGui/QPushButton>
|
|
#include <QtGui/QToolBar>
|
|
#include <QtGui/QMdiArea>
|
|
#include <QtGui/QMdiSubWindow>
|
|
#include <QtGui/QLayout>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
static const char *appFontPrefixC = "AppFonts";
|
|
|
|
typedef QList<QAction *> ActionList;
|
|
|
|
static QMdiSubWindow *mdiSubWindowOf(const QWidget *w)
|
|
{
|
|
QMdiSubWindow *rc = qobject_cast<QMdiSubWindow *>(w->parentWidget());
|
|
Q_ASSERT(rc);
|
|
return rc;
|
|
}
|
|
|
|
static QDockWidget *dockWidgetOf(const QWidget *w)
|
|
{
|
|
for (QWidget *parentWidget = w->parentWidget(); parentWidget ; parentWidget = parentWidget->parentWidget()) {
|
|
if (QDockWidget *dw = qobject_cast<QDockWidget *>(parentWidget)) {
|
|
return dw;
|
|
}
|
|
}
|
|
Q_ASSERT("Dock widget not found");
|
|
return 0;
|
|
}
|
|
|
|
// ------------ QDesignerWorkbench::Position
|
|
QDesignerWorkbench::Position::Position(const QMdiSubWindow *mdiSubWindow, const QPoint &mdiAreaOffset) :
|
|
m_minimized(mdiSubWindow->isShaded()),
|
|
m_position(mdiSubWindow->pos() + mdiAreaOffset)
|
|
{
|
|
}
|
|
|
|
QDesignerWorkbench::Position::Position(const QDockWidget *dockWidget) :
|
|
m_minimized(dockWidget->isMinimized()),
|
|
m_position(dockWidget->pos())
|
|
{
|
|
}
|
|
|
|
QDesignerWorkbench::Position::Position(const QWidget *topLevelWindow, const QPoint &desktopTopLeft)
|
|
{
|
|
const QWidget *window =topLevelWindow->window ();
|
|
Q_ASSERT(window);
|
|
m_minimized = window->isMinimized();
|
|
m_position = window->pos() - desktopTopLeft;
|
|
}
|
|
|
|
void QDesignerWorkbench::Position::applyTo(QMdiSubWindow *mdiSubWindow,
|
|
const QPoint &mdiAreaOffset) const
|
|
{
|
|
// QMdiSubWindow attempts to resize its children to sizeHint() when switching user interface modes.
|
|
// Restore old size
|
|
const QPoint mdiAreaPos = QPoint(qMax(0, m_position.x() - mdiAreaOffset.x()),
|
|
qMax(0, m_position.y() - mdiAreaOffset.y()));
|
|
mdiSubWindow->move(mdiAreaPos);
|
|
const QSize decorationSize = mdiSubWindow->size() - mdiSubWindow->contentsRect().size();
|
|
mdiSubWindow->resize(mdiSubWindow->widget()->size() + decorationSize);
|
|
mdiSubWindow->show();
|
|
if (m_minimized) {
|
|
mdiSubWindow->showShaded();
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::Position::applyTo(QWidget *topLevelWindow, const QPoint &desktopTopLeft) const
|
|
{
|
|
QWidget *window = topLevelWindow->window ();
|
|
const QPoint newPos = m_position + desktopTopLeft;
|
|
window->move(newPos);
|
|
if ( m_minimized) {
|
|
topLevelWindow->showMinimized();
|
|
} else {
|
|
topLevelWindow->show();
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::Position::applyTo(QDockWidget *dockWidget) const
|
|
{
|
|
dockWidget->widget()->setVisible(true);
|
|
dockWidget->setVisible(!m_minimized);
|
|
}
|
|
|
|
static inline void addActionsToMenu(QMenu *m, const ActionList &al)
|
|
{
|
|
const ActionList::const_iterator cend = al.constEnd();
|
|
for (ActionList::const_iterator it = al.constBegin(); it != cend; ++it)
|
|
m->addAction(*it);
|
|
}
|
|
|
|
static inline QMenu *addMenu(QMenuBar *mb, const QString &title, const ActionList &al)
|
|
{
|
|
QMenu *rc = mb->addMenu(title);
|
|
addActionsToMenu(rc, al);
|
|
return rc;
|
|
}
|
|
|
|
// -------- QDesignerWorkbench
|
|
|
|
QDesignerWorkbench::QDesignerWorkbench() :
|
|
m_core(QDesignerComponents::createFormEditor(this)),
|
|
m_windowActions(new QActionGroup(this)),
|
|
m_globalMenuBar(new QMenuBar),
|
|
m_mode(NeutralMode),
|
|
m_dockedMainWindow(0),
|
|
m_state(StateInitializing)
|
|
{
|
|
QDesignerSettings settings(m_core);
|
|
|
|
(void) QDesignerComponents::createTaskMenu(core(), this);
|
|
|
|
initializeCorePlugins();
|
|
QDesignerComponents::initializePlugins(core());
|
|
m_actionManager = new QDesignerActions(this); // accesses plugin components
|
|
|
|
m_windowActions->setExclusive(true);
|
|
connect(m_windowActions, SIGNAL(triggered(QAction*)), this, SLOT(formWindowActionTriggered(QAction*)));
|
|
|
|
// Build main menu bar
|
|
addMenu(m_globalMenuBar, tr("&File"), m_actionManager->fileActions()->actions());
|
|
|
|
QMenu *editMenu = addMenu(m_globalMenuBar, tr("Edit"), m_actionManager->editActions()->actions());
|
|
editMenu->addSeparator();
|
|
addActionsToMenu(editMenu, m_actionManager->toolActions()->actions());
|
|
|
|
QMenu *formMenu = addMenu(m_globalMenuBar, tr("F&orm"), m_actionManager->formActions()->actions());
|
|
QMenu *previewSubMenu = new QMenu(tr("Preview in"), formMenu);
|
|
formMenu->insertMenu(m_actionManager->previewFormAction(), previewSubMenu);
|
|
addActionsToMenu(previewSubMenu, m_actionManager->styleActions()->actions());
|
|
|
|
QMenu *viewMenu = m_globalMenuBar->addMenu(tr("&View"));
|
|
|
|
addMenu(m_globalMenuBar, tr("&Settings"), m_actionManager->settingsActions()->actions());
|
|
|
|
m_windowMenu = addMenu(m_globalMenuBar, tr("&Window"), m_actionManager->windowActions()->actions());
|
|
|
|
addMenu(m_globalMenuBar, tr("&Help"), m_actionManager->helpActions()->actions());
|
|
|
|
// Add the tools in view menu order
|
|
QActionGroup *viewActions = new QActionGroup(this);
|
|
viewActions->setExclusive(false);
|
|
|
|
for (int i = 0; i < QDesignerToolWindow::StandardToolWindowCount; i++) {
|
|
QDesignerToolWindow *toolWindow = QDesignerToolWindow::createStandardToolWindow(static_cast< QDesignerToolWindow::StandardToolWindow>(i), this);
|
|
m_toolWindows.push_back(toolWindow);
|
|
if (QAction *action = toolWindow->action()) {
|
|
viewMenu->addAction(action);
|
|
viewActions->addAction(action);
|
|
}
|
|
// The widget box becomes the main window in top level mode
|
|
if (i == QDesignerToolWindow::WidgetBox)
|
|
connect(toolWindow, SIGNAL(closeEventReceived(QCloseEvent*)), this, SLOT(handleCloseEvent(QCloseEvent*)));
|
|
}
|
|
// Integration
|
|
m_integration = new qdesigner_internal::QDesignerIntegration(m_core, this);
|
|
connect(m_integration, SIGNAL(helpRequested(QString,QString)), m_actionManager, SLOT(helpRequested(QString,QString)));
|
|
|
|
// remaining view options (config toolbars)
|
|
viewMenu->addSeparator();
|
|
m_toolbarMenu = viewMenu->addMenu(tr("Toolbars"));
|
|
|
|
emit initialized();
|
|
|
|
connect(m_core->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
|
|
this, SLOT(updateWindowMenu(QDesignerFormWindowInterface*)));
|
|
|
|
|
|
{ // Add application specific options pages
|
|
QDesignerAppearanceOptionsPage *appearanceOptions = new QDesignerAppearanceOptionsPage(m_core);
|
|
connect(appearanceOptions, SIGNAL(settingsChangedDelayed()), this, SLOT(restoreUISettings()));
|
|
QList<QDesignerOptionsPageInterface*> optionsPages = m_core->optionsPages();
|
|
optionsPages.push_front(appearanceOptions);
|
|
m_core->setOptionsPages(optionsPages);
|
|
}
|
|
|
|
restoreUISettings();
|
|
AppFontWidget::restore(m_core->settingsManager(), QLatin1String(appFontPrefixC));
|
|
m_state = StateUp;
|
|
}
|
|
|
|
QDesignerWorkbench::~QDesignerWorkbench()
|
|
{
|
|
switch (m_mode) {
|
|
case NeutralMode:
|
|
case DockedMode:
|
|
qDeleteAll(m_toolWindows);
|
|
break;
|
|
case TopLevelMode: // Everything parented here
|
|
delete widgetBoxToolWindow();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::saveGeometriesForModeChange()
|
|
{
|
|
m_Positions.clear();
|
|
switch (m_mode) {
|
|
case NeutralMode:
|
|
break;
|
|
case TopLevelMode: {
|
|
const QPoint desktopOffset = QApplication::desktop()->availableGeometry().topLeft();
|
|
foreach (QDesignerToolWindow *tw, m_toolWindows)
|
|
m_Positions.insert(tw, Position(tw, desktopOffset));
|
|
foreach (QDesignerFormWindow *fw, m_formWindows) {
|
|
m_Positions.insert(fw, Position(fw, desktopOffset));
|
|
}
|
|
}
|
|
break;
|
|
case DockedMode: {
|
|
const QPoint mdiAreaOffset = m_dockedMainWindow->mdiArea()->pos();
|
|
foreach (QDesignerToolWindow *tw, m_toolWindows) {
|
|
m_Positions.insert(tw, Position(dockWidgetOf(tw)));
|
|
}
|
|
foreach (QDesignerFormWindow *fw, m_formWindows) {
|
|
m_Positions.insert(fw, Position(mdiSubWindowOf(fw), mdiAreaOffset));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
UIMode QDesignerWorkbench::mode() const
|
|
{
|
|
return m_mode;
|
|
}
|
|
|
|
void QDesignerWorkbench::addFormWindow(QDesignerFormWindow *formWindow)
|
|
{
|
|
// ### Q_ASSERT(formWindow->windowTitle().isEmpty() == false);
|
|
|
|
m_formWindows.append(formWindow);
|
|
|
|
|
|
m_actionManager->setWindowListSeparatorVisible(true);
|
|
|
|
if (QAction *action = formWindow->action()) {
|
|
m_windowActions->addAction(action);
|
|
m_windowMenu->addAction(action);
|
|
action->setChecked(true);
|
|
}
|
|
|
|
m_actionManager->minimizeAction()->setEnabled(true);
|
|
m_actionManager->minimizeAction()->setChecked(false);
|
|
connect(formWindow, SIGNAL(minimizationStateChanged(QDesignerFormWindowInterface*,bool)),
|
|
this, SLOT(minimizationStateChanged(QDesignerFormWindowInterface*,bool)));
|
|
|
|
m_actionManager->editWidgets()->trigger();
|
|
}
|
|
|
|
Qt::WindowFlags QDesignerWorkbench::magicalWindowFlags(const QWidget *widgetForFlags) const
|
|
{
|
|
switch (m_mode) {
|
|
case TopLevelMode: {
|
|
#ifdef Q_WS_MAC
|
|
if (qobject_cast<const QDesignerToolWindow *>(widgetForFlags))
|
|
return Qt::Tool;
|
|
#else
|
|
Q_UNUSED(widgetForFlags);
|
|
#endif
|
|
return Qt::Window;
|
|
}
|
|
case DockedMode:
|
|
return Qt::Window | Qt::WindowShadeButtonHint | Qt::WindowSystemMenuHint | Qt::WindowTitleHint;
|
|
case NeutralMode:
|
|
return Qt::Window;
|
|
default:
|
|
Q_ASSERT(0);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
QWidget *QDesignerWorkbench::magicalParent(const QWidget *w) const
|
|
{
|
|
switch (m_mode) {
|
|
case TopLevelMode: {
|
|
// Use widget box as parent for all windows except self. This will
|
|
// result in having just one entry in the MS Windows task bar.
|
|
QWidget *widgetBoxWrapper = widgetBoxToolWindow();
|
|
return w == widgetBoxWrapper ? 0 : widgetBoxWrapper;
|
|
}
|
|
case DockedMode:
|
|
return m_dockedMainWindow->mdiArea();
|
|
case NeutralMode:
|
|
return 0;
|
|
default:
|
|
Q_ASSERT(0);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::switchToNeutralMode()
|
|
{
|
|
QDesignerSettings settings(m_core);
|
|
saveGeometries(settings);
|
|
saveGeometriesForModeChange();
|
|
|
|
if (m_mode == TopLevelMode) {
|
|
delete m_topLevelData.toolbarManager;
|
|
m_topLevelData.toolbarManager = 0;
|
|
qDeleteAll(m_topLevelData.toolbars);
|
|
m_topLevelData.toolbars.clear();
|
|
}
|
|
|
|
m_mode = NeutralMode;
|
|
|
|
foreach (QDesignerToolWindow *tw, m_toolWindows) {
|
|
tw->setCloseEventPolicy(MainWindowBase::AcceptCloseEvents);
|
|
tw->setParent(0);
|
|
}
|
|
|
|
foreach (QDesignerFormWindow *fw, m_formWindows) {
|
|
fw->setParent(0);
|
|
fw->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
|
}
|
|
|
|
#ifndef Q_WS_MAC
|
|
m_globalMenuBar->setParent(0);
|
|
#endif
|
|
|
|
m_core->setTopLevel(0);
|
|
qDesigner->setMainWindow(0);
|
|
|
|
delete m_dockedMainWindow;
|
|
m_dockedMainWindow = 0;
|
|
}
|
|
|
|
void QDesignerWorkbench::switchToDockedMode()
|
|
{
|
|
if (m_mode == DockedMode)
|
|
return;
|
|
|
|
switchToNeutralMode();
|
|
|
|
#ifndef Q_WS_MAC
|
|
QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow();
|
|
widgetBoxWrapper->action()->setVisible(true);
|
|
widgetBoxWrapper->setWindowTitle(tr("Widget Box"));
|
|
#endif
|
|
|
|
m_mode = DockedMode;
|
|
const QDesignerSettings settings(m_core);
|
|
m_dockedMainWindow = new DockedMainWindow(this, m_toolbarMenu, m_toolWindows);
|
|
m_dockedMainWindow->setUnifiedTitleAndToolBarOnMac(true);
|
|
m_dockedMainWindow->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal);
|
|
connect(m_dockedMainWindow, SIGNAL(closeEventReceived(QCloseEvent*)), this, SLOT(handleCloseEvent(QCloseEvent*)));
|
|
connect(m_dockedMainWindow, SIGNAL(fileDropped(QString)), this, SLOT(slotFileDropped(QString)));
|
|
connect(m_dockedMainWindow, SIGNAL(formWindowActivated(QDesignerFormWindow*)), this, SLOT(slotFormWindowActivated(QDesignerFormWindow*)));
|
|
m_dockedMainWindow->restoreSettings(settings, m_dockedMainWindow->addToolWindows(m_toolWindows), desktopGeometry());
|
|
|
|
m_core->setTopLevel(m_dockedMainWindow);
|
|
|
|
#ifndef Q_WS_MAC
|
|
m_dockedMainWindow->setMenuBar(m_globalMenuBar);
|
|
m_globalMenuBar->show();
|
|
#endif
|
|
qDesigner->setMainWindow(m_dockedMainWindow);
|
|
|
|
foreach (QDesignerFormWindow *fw, m_formWindows) {
|
|
QMdiSubWindow *subwin = m_dockedMainWindow->createMdiSubWindow(fw, magicalWindowFlags(fw),
|
|
m_actionManager->closeFormAction()->shortcut());
|
|
subwin->hide();
|
|
if (QWidget *mainContainer = fw->editor()->mainContainer())
|
|
resizeForm(fw, mainContainer);
|
|
}
|
|
|
|
m_actionManager->setBringAllToFrontVisible(false);
|
|
m_dockedMainWindow->show();
|
|
// Trigger adjustMDIFormPositions() delayed as viewport size is not yet known.
|
|
|
|
if (m_state != StateInitializing)
|
|
QMetaObject::invokeMethod(this, "adjustMDIFormPositions", Qt::QueuedConnection);
|
|
}
|
|
|
|
void QDesignerWorkbench::adjustMDIFormPositions()
|
|
{
|
|
const QPoint mdiAreaOffset = m_dockedMainWindow->mdiArea()->pos();
|
|
|
|
foreach (QDesignerFormWindow *fw, m_formWindows) {
|
|
const PositionMap::const_iterator pit = m_Positions.constFind(fw);
|
|
if (pit != m_Positions.constEnd())
|
|
pit->applyTo(mdiSubWindowOf(fw), mdiAreaOffset);
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::switchToTopLevelMode()
|
|
{
|
|
if (m_mode == TopLevelMode)
|
|
return;
|
|
|
|
// make sure that the widgetbox is visible if it is different from neutral.
|
|
QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow();
|
|
Q_ASSERT(widgetBoxWrapper);
|
|
|
|
switchToNeutralMode();
|
|
const QPoint desktopOffset = desktopGeometry().topLeft();
|
|
m_mode = TopLevelMode;
|
|
|
|
// The widget box is special, it gets the menubar and gets to be the main widget.
|
|
|
|
m_core->setTopLevel(widgetBoxWrapper);
|
|
#ifndef Q_WS_MAC
|
|
widgetBoxWrapper->setMenuBar(m_globalMenuBar);
|
|
widgetBoxWrapper->action()->setVisible(false);
|
|
widgetBoxWrapper->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal);
|
|
qDesigner->setMainWindow(widgetBoxWrapper);
|
|
widgetBoxWrapper->setWindowTitle(MainWindowBase::mainWindowTitle());
|
|
#endif
|
|
|
|
const QDesignerSettings settings(m_core);
|
|
m_topLevelData.toolbars = MainWindowBase::createToolBars(m_actionManager, false);
|
|
m_topLevelData.toolbarManager = new ToolBarManager(widgetBoxWrapper, widgetBoxWrapper,
|
|
m_toolbarMenu, m_actionManager,
|
|
m_topLevelData.toolbars, m_toolWindows);
|
|
const int toolBarCount = m_topLevelData.toolbars.size();
|
|
for (int i = 0; i < toolBarCount; i++) {
|
|
widgetBoxWrapper->addToolBar(m_topLevelData.toolbars.at(i));
|
|
if (i == 3)
|
|
widgetBoxWrapper->insertToolBarBreak(m_topLevelData.toolbars.at(i));
|
|
}
|
|
m_topLevelData.toolbarManager->restoreState(settings.toolBarsState(m_mode), MainWindowBase::settingsVersion());
|
|
widgetBoxWrapper->restoreState(settings.mainWindowState(m_mode), MainWindowBase::settingsVersion());
|
|
|
|
bool found_visible_window = false;
|
|
foreach (QDesignerToolWindow *tw, m_toolWindows) {
|
|
tw->setParent(magicalParent(tw), magicalWindowFlags(tw));
|
|
settings.restoreGeometry(tw, tw->geometryHint());
|
|
tw->action()->setChecked(tw->isVisible());
|
|
found_visible_window |= tw->isVisible();
|
|
}
|
|
|
|
if (!m_toolWindows.isEmpty() && !found_visible_window)
|
|
m_toolWindows.first()->show();
|
|
|
|
m_actionManager->setBringAllToFrontVisible(true);
|
|
|
|
foreach (QDesignerFormWindow *fw, m_formWindows) {
|
|
fw->setParent(magicalParent(fw), magicalWindowFlags(fw));
|
|
fw->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
const PositionMap::const_iterator pit = m_Positions.constFind(fw);
|
|
if (pit != m_Positions.constEnd()) pit->applyTo(fw, desktopOffset);
|
|
// Force an activate in order to refresh minimumSize, otherwise it will not be respected
|
|
if (QLayout *layout = fw->layout())
|
|
layout->invalidate();
|
|
if (QWidget *mainContainer = fw->editor()->mainContainer())
|
|
resizeForm(fw, mainContainer);
|
|
}
|
|
}
|
|
|
|
QDesignerFormWindowManagerInterface *QDesignerWorkbench::formWindowManager() const
|
|
{
|
|
return m_core->formWindowManager();
|
|
}
|
|
|
|
QDesignerFormEditorInterface *QDesignerWorkbench::core() const
|
|
{
|
|
return m_core;
|
|
}
|
|
|
|
int QDesignerWorkbench::toolWindowCount() const
|
|
{
|
|
return m_toolWindows.count();
|
|
}
|
|
|
|
QDesignerToolWindow *QDesignerWorkbench::toolWindow(int index) const
|
|
{
|
|
return m_toolWindows.at(index);
|
|
}
|
|
|
|
int QDesignerWorkbench::formWindowCount() const
|
|
{
|
|
return m_formWindows.count();
|
|
}
|
|
|
|
QDesignerFormWindow *QDesignerWorkbench::formWindow(int index) const
|
|
{
|
|
return m_formWindows.at(index);
|
|
}
|
|
|
|
QRect QDesignerWorkbench::desktopGeometry() const
|
|
{
|
|
// Return geometry of the desktop designer is running in.
|
|
QWidget *widget = 0;
|
|
switch (m_mode) {
|
|
case DockedMode:
|
|
widget = m_dockedMainWindow;
|
|
break;
|
|
case TopLevelMode:
|
|
widget = widgetBoxToolWindow();
|
|
break;
|
|
case NeutralMode:
|
|
break;
|
|
}
|
|
const QDesktopWidget *desktop = qApp->desktop();
|
|
const int screenNumber = widget ? desktop->screenNumber(widget) : 0;
|
|
return desktop->availableGeometry(screenNumber);
|
|
}
|
|
|
|
QRect QDesignerWorkbench::availableGeometry() const
|
|
{
|
|
if (m_mode == DockedMode)
|
|
return m_dockedMainWindow->mdiArea()->geometry();
|
|
|
|
const QDesktopWidget *desktop = qDesigner->desktop();
|
|
return desktop->availableGeometry(desktop->screenNumber(widgetBoxToolWindow()));
|
|
}
|
|
|
|
int QDesignerWorkbench::marginHint() const
|
|
{ return 20;
|
|
}
|
|
|
|
void QDesignerWorkbench::slotFormWindowActivated(QDesignerFormWindow* fw)
|
|
{
|
|
core()->formWindowManager()->setActiveFormWindow(fw->editor());
|
|
}
|
|
|
|
void QDesignerWorkbench::removeFormWindow(QDesignerFormWindow *formWindow)
|
|
{
|
|
QDesignerFormWindowInterface *editor = formWindow->editor();
|
|
const bool loadOk = editor->mainContainer();
|
|
updateBackup(editor);
|
|
const int index = m_formWindows.indexOf(formWindow);
|
|
if (index != -1) {
|
|
m_formWindows.removeAt(index);
|
|
}
|
|
|
|
if (QAction *action = formWindow->action()) {
|
|
m_windowActions->removeAction(action);
|
|
m_windowMenu->removeAction(action);
|
|
}
|
|
|
|
if (m_formWindows.empty()) {
|
|
m_actionManager->setWindowListSeparatorVisible(false);
|
|
// Show up new form dialog unless closing
|
|
if (loadOk && m_state == StateUp
|
|
&& QDesignerSettings(m_core).showNewFormOnStartup()) {
|
|
QTimer::singleShot(200, m_actionManager, SLOT(createForm()));
|
|
}
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::initializeCorePlugins()
|
|
{
|
|
QList<QObject*> plugins = QPluginLoader::staticInstances();
|
|
plugins += core()->pluginManager()->instances();
|
|
|
|
foreach (QObject *plugin, plugins) {
|
|
if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
|
|
if (!formEditorPlugin->isInitialized())
|
|
formEditorPlugin->initialize(core());
|
|
}
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::saveSettings() const
|
|
{
|
|
QDesignerSettings settings(m_core);
|
|
settings.clearBackup();
|
|
saveGeometries(settings);
|
|
AppFontWidget::save(m_core->settingsManager(), QLatin1String(appFontPrefixC));
|
|
}
|
|
|
|
void QDesignerWorkbench::saveGeometries(QDesignerSettings &settings) const
|
|
{
|
|
switch (m_mode) {
|
|
case DockedMode:
|
|
m_dockedMainWindow->saveSettings(settings);
|
|
break;
|
|
case TopLevelMode:
|
|
settings.setToolBarsState(m_mode, m_topLevelData.toolbarManager->saveState(MainWindowBase::settingsVersion()));
|
|
settings.setMainWindowState(m_mode, widgetBoxToolWindow()->saveState(MainWindowBase::settingsVersion()));
|
|
foreach (const QDesignerToolWindow *tw, m_toolWindows)
|
|
settings.saveGeometryFor(tw);
|
|
break;
|
|
case NeutralMode:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::slotFileDropped(const QString &f)
|
|
{
|
|
readInForm(f);
|
|
}
|
|
|
|
bool QDesignerWorkbench::readInForm(const QString &fileName) const
|
|
{
|
|
return m_actionManager->readInForm(fileName);
|
|
}
|
|
|
|
bool QDesignerWorkbench::writeOutForm(QDesignerFormWindowInterface *formWindow, const QString &fileName) const
|
|
{
|
|
return m_actionManager->writeOutForm(formWindow, fileName);
|
|
}
|
|
|
|
bool QDesignerWorkbench::saveForm(QDesignerFormWindowInterface *frm)
|
|
{
|
|
return m_actionManager->saveForm(frm);
|
|
}
|
|
|
|
QDesignerFormWindow *QDesignerWorkbench::findFormWindow(QWidget *widget) const
|
|
{
|
|
foreach (QDesignerFormWindow *formWindow, m_formWindows) {
|
|
if (formWindow->editor() == widget)
|
|
return formWindow;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool QDesignerWorkbench::handleClose()
|
|
{
|
|
m_state = StateClosing;
|
|
QList<QDesignerFormWindow *> dirtyForms;
|
|
foreach (QDesignerFormWindow *w, m_formWindows) {
|
|
if (w->editor()->isDirty())
|
|
dirtyForms << w;
|
|
}
|
|
|
|
if (dirtyForms.size()) {
|
|
if (dirtyForms.size() == 1) {
|
|
if (!dirtyForms.at(0)->close()) {
|
|
m_state = StateUp;
|
|
return false;
|
|
}
|
|
} else {
|
|
int count = dirtyForms.size();
|
|
QMessageBox box(QMessageBox::Warning, tr("Save Forms?"),
|
|
tr("There are %n forms with unsaved changes."
|
|
" Do you want to review these changes before quitting?", "", count),
|
|
QMessageBox::Cancel | QMessageBox::Discard | QMessageBox::Save);
|
|
box.setInformativeText(tr("If you do not review your documents, all your changes will be lost."));
|
|
box.button(QMessageBox::Discard)->setText(tr("Discard Changes"));
|
|
QPushButton *save = static_cast<QPushButton *>(box.button(QMessageBox::Save));
|
|
save->setText(tr("Review Changes"));
|
|
box.setDefaultButton(save);
|
|
switch (box.exec()) {
|
|
case QMessageBox::Cancel:
|
|
m_state = StateUp;
|
|
return false;
|
|
case QMessageBox::Save:
|
|
foreach (QDesignerFormWindow *fw, dirtyForms) {
|
|
fw->show();
|
|
fw->raise();
|
|
if (!fw->close()) {
|
|
m_state = StateUp;
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
case QMessageBox::Discard:
|
|
foreach (QDesignerFormWindow *fw, dirtyForms) {
|
|
fw->editor()->setDirty(false);
|
|
fw->setWindowModified(false);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (QDesignerFormWindow *fw, m_formWindows)
|
|
fw->close();
|
|
|
|
saveSettings();
|
|
return true;
|
|
}
|
|
|
|
QDesignerActions *QDesignerWorkbench::actionManager() const
|
|
{
|
|
return m_actionManager;
|
|
}
|
|
|
|
void QDesignerWorkbench::updateWindowMenu(QDesignerFormWindowInterface *fwi)
|
|
{
|
|
bool minimizeChecked = false;
|
|
bool minimizeEnabled = false;
|
|
QDesignerFormWindow *activeFormWindow = 0;
|
|
do {
|
|
if (!fwi)
|
|
break;
|
|
activeFormWindow = qobject_cast<QDesignerFormWindow *>(fwi->parentWidget());
|
|
if (!activeFormWindow)
|
|
break;
|
|
|
|
minimizeEnabled = true;
|
|
minimizeChecked = isFormWindowMinimized(activeFormWindow);
|
|
} while (false) ;
|
|
|
|
m_actionManager->minimizeAction()->setEnabled(minimizeEnabled);
|
|
m_actionManager->minimizeAction()->setChecked(minimizeChecked);
|
|
|
|
if (!m_formWindows.empty()) {
|
|
const QList<QDesignerFormWindow*>::const_iterator cend = m_formWindows.constEnd();
|
|
for (QList<QDesignerFormWindow*>::const_iterator it = m_formWindows.constBegin(); it != cend; ++it)
|
|
(*it)->action()->setChecked(*it == activeFormWindow);
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::formWindowActionTriggered(QAction *a)
|
|
{
|
|
QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow *>(a->parentWidget());
|
|
Q_ASSERT(fw);
|
|
|
|
if (isFormWindowMinimized(fw))
|
|
setFormWindowMinimized(fw, false);
|
|
|
|
if (m_mode == DockedMode) {
|
|
if (QMdiSubWindow *subWindow = qobject_cast<QMdiSubWindow *>(fw->parent())) {
|
|
m_dockedMainWindow->mdiArea()->setActiveSubWindow(subWindow);
|
|
}
|
|
} else {
|
|
fw->activateWindow();
|
|
fw->raise();
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::closeAllToolWindows()
|
|
{
|
|
foreach (QDesignerToolWindow *tw, m_toolWindows)
|
|
tw->hide();
|
|
}
|
|
|
|
bool QDesignerWorkbench::readInBackup()
|
|
{
|
|
const QMap<QString, QString> backupFileMap = QDesignerSettings(m_core).backup();
|
|
if (backupFileMap.isEmpty())
|
|
return false;
|
|
|
|
const QMessageBox::StandardButton answer =
|
|
QMessageBox::question(0, tr("Backup Information"),
|
|
tr("The last session of Designer was not terminated correctly. "
|
|
"Backup files were left behind. Do you want to load them?"),
|
|
QMessageBox::Yes|QMessageBox::No, QMessageBox::Yes);
|
|
if (answer == QMessageBox::No)
|
|
return false;
|
|
|
|
const QString modifiedPlaceHolder = QLatin1String("[*]");
|
|
QMapIterator<QString, QString> it(backupFileMap);
|
|
while(it.hasNext()) {
|
|
it.next();
|
|
|
|
QString fileName = it.key();
|
|
fileName.remove(modifiedPlaceHolder);
|
|
|
|
if(m_actionManager->readInForm(it.value()))
|
|
formWindowManager()->activeFormWindow()->setFileName(fileName);
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void QDesignerWorkbench::updateBackup(QDesignerFormWindowInterface* fwi)
|
|
{
|
|
QString fwn = QDir::convertSeparators(fwi->fileName());
|
|
if (fwn.isEmpty())
|
|
fwn = fwi->parentWidget()->windowTitle();
|
|
|
|
QDesignerSettings settings(m_core);
|
|
QMap<QString, QString> map = settings.backup();
|
|
map.remove(fwn);
|
|
settings.setBackup(map);
|
|
}
|
|
|
|
namespace {
|
|
void raiseWindow(QWidget *w) {
|
|
if (w->isMinimized())
|
|
w->setWindowState(w->windowState() & ~Qt::WindowMinimized);
|
|
w->raise();
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::bringAllToFront()
|
|
{
|
|
if (m_mode != TopLevelMode)
|
|
return;
|
|
foreach(QDesignerToolWindow *tw, m_toolWindows)
|
|
raiseWindow(tw);
|
|
foreach(QDesignerFormWindow *dfw, m_formWindows)
|
|
raiseWindow(dfw);
|
|
}
|
|
|
|
// Resize a form window taking MDI decorations into account
|
|
// Apply maximum size as there is no layout connection between
|
|
// the form's main container and the integration's outer
|
|
// container due to the tool widget stack.
|
|
|
|
void QDesignerWorkbench::resizeForm(QDesignerFormWindow *fw, const QWidget *mainContainer) const
|
|
{
|
|
const QSize containerSize = mainContainer->size();
|
|
const QSize containerMinimumSize = mainContainer->minimumSize();
|
|
const QSize containerMaximumSize = mainContainer->maximumSize();
|
|
if (m_mode != DockedMode) {
|
|
fw->resize(containerSize);
|
|
fw->setMaximumSize(containerMaximumSize);
|
|
return;
|
|
}
|
|
// get decorations and resize MDI
|
|
QMdiSubWindow *mdiSubWindow = qobject_cast<QMdiSubWindow *>(fw->parent());
|
|
Q_ASSERT(mdiSubWindow);
|
|
const QSize decorationSize = mdiSubWindow->geometry().size() - mdiSubWindow->contentsRect().size();
|
|
mdiSubWindow->resize(containerSize + decorationSize);
|
|
// In Qt::RightToLeft mode, the window can grow to be partially hidden by the right border.
|
|
const int mdiAreaWidth = m_dockedMainWindow->mdiArea()->width();
|
|
if (qApp->layoutDirection() == Qt::RightToLeft && mdiSubWindow->geometry().right() >= mdiAreaWidth)
|
|
mdiSubWindow->move(mdiAreaWidth - mdiSubWindow->width(), mdiSubWindow->pos().y());
|
|
|
|
if (containerMaximumSize == QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) {
|
|
mdiSubWindow->setMaximumSize(containerMaximumSize);
|
|
} else {
|
|
mdiSubWindow->setMaximumSize(containerMaximumSize + decorationSize);
|
|
}
|
|
}
|
|
|
|
|
|
// Load a form or return 0 and do cleanup. file name and editor file
|
|
// name in case of loading a template file.
|
|
|
|
QDesignerFormWindow * QDesignerWorkbench::loadForm(const QString &fileName,
|
|
bool detectLineTermiantorMode,
|
|
bool *uic3Converted,
|
|
QString *errorMessage)
|
|
{
|
|
QFile file(fileName);
|
|
|
|
qdesigner_internal::FormWindowBase::LineTerminatorMode mode = qdesigner_internal::FormWindowBase::NativeLineTerminator;
|
|
|
|
if (detectLineTermiantorMode) {
|
|
if (file.open(QFile::ReadOnly)) {
|
|
const QString text = QString::fromUtf8(file.readLine());
|
|
file.close();
|
|
|
|
const int lf = text.indexOf(QLatin1Char('\n'));
|
|
if (lf > 0 && text.at(lf-1) == QLatin1Char('\r')) {
|
|
mode = qdesigner_internal::FormWindowBase::CRLFLineTerminator;
|
|
} else if (lf >= 0) {
|
|
mode = qdesigner_internal::FormWindowBase::LFLineTerminator;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!file.open(QFile::ReadOnly|QFile::Text)) {
|
|
*errorMessage = tr("The file <b>%1</b> could not be opened.").arg(file.fileName());
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Create a form
|
|
QDesignerFormWindowManagerInterface *formWindowManager = m_core->formWindowManager();
|
|
|
|
QDesignerFormWindow *formWindow = new QDesignerFormWindow(/*formWindow=*/ 0, this);
|
|
addFormWindow(formWindow);
|
|
QDesignerFormWindowInterface *editor = formWindow->editor();
|
|
Q_ASSERT(editor);
|
|
|
|
// Temporarily set the file name. It is needed when converting a UIC 3 file.
|
|
// In this case, the file name will we be cleared on return to force a save box.
|
|
editor->setFileName(fileName);
|
|
editor->setContents(&file);
|
|
|
|
if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(editor))
|
|
fwb->setLineTerminatorMode(mode);
|
|
|
|
switch (m_mode) {
|
|
case DockedMode: {
|
|
// below code must be after above call to setContents(), because setContents() may popup warning dialogs which would cause
|
|
// mdi sub window activation (because of dialogs internal call to processEvent or such)
|
|
// That activation could have worse consequences, e.g. NULL resource set for active form) before the form is loaded
|
|
QMdiSubWindow *subWin = m_dockedMainWindow->createMdiSubWindow(formWindow, magicalWindowFlags(formWindow), m_actionManager->closeFormAction()->shortcut());
|
|
m_dockedMainWindow->mdiArea()->setActiveSubWindow(subWin);
|
|
}
|
|
break;
|
|
case TopLevelMode: {
|
|
const QRect formWindowGeometryHint = formWindow->geometryHint();
|
|
formWindow->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
formWindow->setParent(magicalParent(formWindow), magicalWindowFlags(formWindow));
|
|
formWindow->resize(formWindowGeometryHint.size());
|
|
formWindow->move(availableGeometry().center() - formWindowGeometryHint.center());
|
|
}
|
|
break;
|
|
case NeutralMode:
|
|
break;
|
|
}
|
|
|
|
if (!editor->mainContainer()) {
|
|
removeFormWindow(formWindow);
|
|
formWindowManager->removeFormWindow(editor);
|
|
m_core->metaDataBase()->remove(editor);
|
|
*errorMessage = tr("The file <b>%1</b> is not a valid Designer UI file.").arg(file.fileName());
|
|
return 0;
|
|
}
|
|
*uic3Converted = editor->fileName().isEmpty();
|
|
editor->setDirty(false);
|
|
resizeForm(formWindow, editor->mainContainer());
|
|
formWindowManager->setActiveFormWindow(editor);
|
|
return formWindow;
|
|
}
|
|
|
|
|
|
QDesignerFormWindow * QDesignerWorkbench::openForm(const QString &fileName, QString *errorMessage)
|
|
{
|
|
bool uic3Converted;
|
|
QDesignerFormWindow *rc =loadForm(fileName, true, &uic3Converted, errorMessage);
|
|
if (!rc)
|
|
return 0;
|
|
|
|
if (!uic3Converted)
|
|
rc->editor()->setFileName(fileName);
|
|
rc->firstShow();
|
|
return rc;
|
|
}
|
|
|
|
QDesignerFormWindow * QDesignerWorkbench::openTemplate(const QString &templateFileName,
|
|
const QString &editorFileName,
|
|
QString *errorMessage)
|
|
{
|
|
bool uic3Converted;
|
|
QDesignerFormWindow *rc =loadForm(templateFileName, false, &uic3Converted, errorMessage);
|
|
if (!rc)
|
|
return 0;
|
|
|
|
if (!uic3Converted)
|
|
rc->editor()->setFileName(editorFileName);
|
|
|
|
rc->firstShow();
|
|
return rc;
|
|
}
|
|
|
|
void QDesignerWorkbench::minimizationStateChanged(QDesignerFormWindowInterface *formWindow, bool minimized)
|
|
{
|
|
// refresh the minimize action state
|
|
if (core()->formWindowManager()->activeFormWindow() == formWindow) {
|
|
m_actionManager->minimizeAction()->setChecked(minimized);
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::toggleFormMinimizationState()
|
|
{
|
|
QDesignerFormWindowInterface *fwi = core()->formWindowManager()->activeFormWindow();
|
|
if (!fwi || m_mode == NeutralMode)
|
|
return;
|
|
QDesignerFormWindow *fw = qobject_cast<QDesignerFormWindow *>(fwi->parentWidget());
|
|
Q_ASSERT(fw);
|
|
setFormWindowMinimized(fw, !isFormWindowMinimized(fw));
|
|
}
|
|
|
|
bool QDesignerWorkbench::isFormWindowMinimized(const QDesignerFormWindow *fw)
|
|
{
|
|
switch (m_mode) {
|
|
case DockedMode:
|
|
return mdiSubWindowOf(fw)->isShaded();
|
|
case TopLevelMode:
|
|
return fw->window()->isMinimized();
|
|
default:
|
|
break;
|
|
}
|
|
return fw->isMinimized();
|
|
}
|
|
|
|
void QDesignerWorkbench::setFormWindowMinimized(QDesignerFormWindow *fw, bool minimized)
|
|
{
|
|
switch (m_mode) {
|
|
case DockedMode: {
|
|
QMdiSubWindow *mdiSubWindow = mdiSubWindowOf(fw);
|
|
if (minimized) {
|
|
mdiSubWindow->showShaded();
|
|
} else {
|
|
mdiSubWindow->setWindowState(mdiSubWindow->windowState() & ~Qt::WindowMinimized);
|
|
}
|
|
}
|
|
break;
|
|
case TopLevelMode: {
|
|
QWidget *window = fw->window();
|
|
if (window->isMinimized()) {
|
|
window->setWindowState(window->windowState() & ~Qt::WindowMinimized);
|
|
} else {
|
|
window->showMinimized();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void QDesignerWorkbench::restoreUISettings()
|
|
{
|
|
UIMode mode = QDesignerSettings(m_core).uiMode();
|
|
switch (mode) {
|
|
case TopLevelMode:
|
|
switchToTopLevelMode();
|
|
break;
|
|
case DockedMode:
|
|
switchToDockedMode();
|
|
break;
|
|
|
|
default: Q_ASSERT(0);
|
|
}
|
|
|
|
ToolWindowFontSettings fontSettings = QDesignerSettings(m_core).toolWindowFont();
|
|
const QFont &font = fontSettings.m_useFont ? fontSettings.m_font : qApp->font();
|
|
|
|
if (font == m_toolWindows.front()->font())
|
|
return;
|
|
|
|
foreach(QDesignerToolWindow *tw, m_toolWindows)
|
|
tw->setFont(font);
|
|
}
|
|
|
|
void QDesignerWorkbench::handleCloseEvent(QCloseEvent *ev)
|
|
{
|
|
ev->setAccepted(handleClose());
|
|
if (ev->isAccepted())
|
|
QMetaObject::invokeMethod(qDesigner, "quit", Qt::QueuedConnection); // We're going down!
|
|
}
|
|
|
|
QDesignerToolWindow *QDesignerWorkbench::widgetBoxToolWindow() const
|
|
{
|
|
return m_toolWindows.at(QDesignerToolWindow::WidgetBox);
|
|
}
|
|
|
|
QT_END_NAMESPACE
|