formeditorw.cpp 37.6 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.nokia.com)
con's avatar
con committed
8
**
9
**
10
** GNU Lesser General Public License Usage
11
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
Tobias Hunger's avatar
Tobias Hunger committed
29
** Nokia at info@qt.nokia.com.
con's avatar
con committed
30
**
31
**************************************************************************/
hjk's avatar
hjk committed
32

con's avatar
con committed
33 34 35 36 37 38
#include "formeditorw.h"
#include "formwindoweditor.h"
#include "designerconstants.h"
#include "settingsmanager.h"
#include "settingspage.h"
#include "editorwidget.h"
39
#include "editordata.h"
40
#include "qtcreatorintegration.h"
Lasse Holmstedt's avatar
Lasse Holmstedt committed
41 42
#include "designerxmleditor.h"
#include "designercontext.h"
43
#include "editorwidget.h"
44
#include "resourcehandler.h"
45
#include <widgethost.h>
con's avatar
con committed
46

47
#include <coreplugin/editortoolbar.h>
Lasse Holmstedt's avatar
Lasse Holmstedt committed
48
#include <coreplugin/designmode.h>
con's avatar
con committed
49
#include <coreplugin/coreconstants.h>
50
#include <coreplugin/icore.h>
kh1's avatar
kh1 committed
51
#include <coreplugin/helpmanager.h>
52
#include <coreplugin/actionmanager/actionmanager.h>
53 54
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
55
#include <coreplugin/id.h>
con's avatar
con committed
56
#include <coreplugin/editormanager/editormanager.h>
57
#include <coreplugin/minisplitter.h>
58
#include <coreplugin/mimedatabase.h>
59
#include <coreplugin/outputpane.h>
60
#include <texteditor/texteditorsettings.h>
61
#include <extensionsystem/pluginmanager.h>
62
#include <cpptools/cpptoolsconstants.h>
hjk's avatar
hjk committed
63
#include <utils/qtcassert.h>
con's avatar
con committed
64 65 66 67 68

#include <QtDesigner/QDesignerFormEditorPluginInterface>
#include <QtDesigner/QDesignerFormEditorInterface>
#include <QtDesigner/QDesignerComponents>

69 70 71 72 73 74 75 76 77
#if QT_VERSION >= 0x050000
#    include <QtDesigner/QDesignerFormWindowManagerInterface>
#else
#    include "qt_private/pluginmanager_p.h"
#    include "qt_private/iconloader_p.h"  // createIconSet
#    include "qt_private/qdesigner_formwindowmanager_p.h"
#    include "qt_private/formwindowbase_p.h"
#endif

con's avatar
con committed
78 79 80 81
#include <QtDesigner/QDesignerWidgetBoxInterface>
#include <QtDesigner/abstractobjectinspector.h>
#include <QtDesigner/QDesignerPropertyEditorInterface>
#include <QtDesigner/QDesignerActionEditorInterface>
82
#include <QtDesigner/QDesignerFormEditorInterface>
con's avatar
con committed
83 84 85 86 87

#include <QtGui/QAction>
#include <QtGui/QActionGroup>
#include <QtGui/QApplication>
#include <QtGui/QCursor>
con's avatar
con committed
88
#include <QtGui/QDockWidget>
con's avatar
con committed
89 90 91 92 93 94 95 96 97
#include <QtGui/QMenu>
#include <QtGui/QMainWindow>
#include <QtGui/QMessageBox>
#include <QtGui/QKeySequence>
#include <QtGui/QPrintDialog>
#include <QtGui/QPrinter>
#include <QtGui/QPainter>
#include <QtGui/QStyle>
#include <QtGui/QToolBar>
98
#include <QtGui/QVBoxLayout>
con's avatar
con committed
99 100 101

#include <QtCore/QDebug>
#include <QtCore/QSettings>
102 103 104
#include <QtCore/QSignalMapper>
#include <QtCore/QPluginLoader>
#include <QtCore/QTime>
con's avatar
con committed
105

106
static const char settingsGroup[] = "Designer";
con's avatar
con committed
107

108 109 110 111 112 113 114 115
#ifdef Q_OS_MAC
    enum { osMac = 1 };
#else
    enum { osMac = 0 };
#endif

/* Actions of the designer plugin:
 * Designer provides a toolbar which is subject to a context change (to
Tobias Hunger's avatar
Tobias Hunger committed
116
 * "edit mode" context) when it is focused.
117 118 119 120 121
 * In order to prevent its actions from being disabled/hidden by that context
 * change, the actions are registered on the global context. In currentEditorChanged(),
 * the ones that are present in the global edit menu are set visible/invisible manually.
 * The designer context is currently used for Cut/Copy/Paste, etc. */

con's avatar
con committed
122 123
static inline QIcon designerIcon(const QString &iconName)
{
124 125 126
#if QT_VERSION >= 0x050000
    const QIcon icon = QDesignerFormEditorInterface::createIcon(iconName);
#else
con's avatar
con committed
127
    const QIcon icon = qdesigner_internal::createIconSet(iconName);
128
#endif
con's avatar
con committed
129 130 131 132 133
    if (icon.isNull())
        qWarning() << "Unable to locate " << iconName;
    return icon;
}

134 135
// Create a menu separator
static inline QAction *createSeparator(QObject *parent,
136
                                 Core::ActionManager *am,
137
                                 const Core::Context &context,
138
                                 Core::ActionContainer *container,
con's avatar
con committed
139 140 141 142 143
                                 const QString &name = QString(),
                                 const QString &group = QString())
{
    QAction *actSeparator = new QAction(parent);
    actSeparator->setSeparator(true);
con's avatar
con committed
144
    Core::Command *command = am->registerAction(actSeparator, name, context);
con's avatar
con committed
145 146 147 148 149 150
    container->addAction(command, group);
    return actSeparator;
}

using namespace Designer::Constants;

151 152
namespace Designer {
namespace Internal {
con's avatar
con committed
153 154 155

// --------- FormEditorW

con's avatar
con committed
156 157 158 159 160 161
FormEditorW *FormEditorW::m_self = 0;

FormEditorW::FormEditorW() :
    m_formeditor(QDesignerComponents::createFormEditor(0)),
    m_integration(0),
    m_fwm(0),
162
    m_core(Core::ICore::instance()),
con's avatar
con committed
163 164
    m_initStage(RegisterPlugins),
    m_actionGroupEditMode(0),
165 166 167
    m_actionPrint(0),
    m_actionPreview(0),
    m_actionGroupPreviewInStyle(0),
168
    m_previewInStyleMenu(0),
169
    m_actionAboutPlugins(0),
170
    m_actionSwitchSource(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
171 172
    m_shortcutMapper(new QSignalMapper(this)),
    m_context(0),
173 174
    m_modeWidget(0),
    m_editorWidget(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
175 176 177
    m_designMode(0),
    m_editorToolBar(0),
    m_toolBar(0)
con's avatar
con committed
178
{
179
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
180
        qDebug() << Q_FUNC_INFO;
hjk's avatar
hjk committed
181
    QTC_ASSERT(!m_self, return);
con's avatar
con committed
182
    m_self = this;
hjk's avatar
hjk committed
183
    QTC_ASSERT(m_core, return);
con's avatar
con committed
184 185 186 187 188 189 190

    qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount,
          static_cast<QWidget *>(0));

    m_formeditor->setTopLevel(qobject_cast<QWidget *>(m_core->editorManager()));
    m_formeditor->setSettingsManager(new SettingsManager());

191 192 193
#if QT_VERSION >= 0x050000
    m_fwm = m_formeditor->formWindowManager();
#else
con's avatar
con committed
194
    m_fwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager*>(m_formeditor->formWindowManager());
195
#endif
hjk's avatar
hjk committed
196
    QTC_ASSERT(m_fwm, return);
con's avatar
con committed
197

198
    m_contexts.add(Designer::Constants::C_FORMEDITOR);
199

con's avatar
con committed
200 201 202 203 204 205 206 207 208
    setupActions();

    foreach (QDesignerOptionsPageInterface *designerPage, m_formeditor->optionsPages()) {
        SettingsPage *settingsPage = new SettingsPage(designerPage);
        m_settingsPages.append(settingsPage);
    }

    connect(m_core->editorManager(), SIGNAL(currentEditorChanged(Core::IEditor *)),
            this, SLOT(currentEditorChanged(Core::IEditor *)));
209 210
    connect(m_shortcutMapper, SIGNAL(mapped(QObject *)),
            this, SLOT(updateShortcut(QObject *)));
con's avatar
con committed
211 212 213 214
}

FormEditorW::~FormEditorW()
{
215 216
    if (m_context)
        m_core->removeContextObject(m_context);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
217
    if (m_initStage == FullyInitialized) {
218 219 220 221 222
        if (QSettings *s = m_core->settings()) {
            m_core->settings()->beginGroup(settingsGroup);
            m_editorWidget->saveSettings(s);
            s->endGroup();
        }
Lasse Holmstedt's avatar
Lasse Holmstedt committed
223

224 225 226 227
        m_designMode->unregisterDesignWidget(m_modeWidget);
        delete m_modeWidget;
        m_modeWidget = 0;
    }
con's avatar
con committed
228 229

    delete m_formeditor;
230 231
    qDeleteAll(m_settingsPages);
    m_settingsPages.clear();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
232 233
    delete m_integration;

234 235 236
    m_self = 0;
}

237
// Add an actioon to toggle the view state of a dock window
238
void FormEditorW::addDockViewAction(Core::ActionManager *am,
239
                                    Core::ActionContainer *viewMenu,
240
                                    int index, const Core::Context &context,
241 242 243 244 245
                                    const QString &title, const QString &id)
{
    if (const QDockWidget *dw = m_editorWidget->designerDockWidgets()[index]) {
        QAction *action = dw->toggleViewAction();
        action->setText(title);
246 247
        Core::Command *cmd = addToolAction(action, am, context, id, viewMenu, QString());
        cmd->setAttribute(Core::Command::CA_Hide);
248 249 250 251 252 253 254
    }
}

void FormEditorW::setupViewActions()
{
    // Populate "View" menu of form editor menu
    Core::ActionManager *am = m_core->actionManager();
hjk's avatar
hjk committed
255
    Core::ActionContainer *viewMenu = am->actionContainer(Core::Id(Core::Constants::M_WINDOW_VIEWS));
256
    QTC_ASSERT(viewMenu, return)
257

258
    addDockViewAction(am, viewMenu, WidgetBoxSubWindow, m_contexts,
259
                      tr("Widget box"), QLatin1String("FormEditor.WidgetBox"));
Lasse Holmstedt's avatar
Lasse Holmstedt committed
260

261
    addDockViewAction(am, viewMenu, ObjectInspectorSubWindow, m_contexts,
262
                      tr("Object Inspector"), QLatin1String("FormEditor.ObjectInspector"));
Lasse Holmstedt's avatar
Lasse Holmstedt committed
263

264
    addDockViewAction(am, viewMenu, PropertyEditorSubWindow, m_contexts,
265 266
                      tr("Property Editor"), QLatin1String("FormEditor.PropertyEditor"));

267
    addDockViewAction(am, viewMenu, SignalSlotEditorSubWindow, m_contexts,
268 269
                      tr("Signals && Slots Editor"), QLatin1String("FormEditor.SignalsAndSlotsEditor"));

270
    addDockViewAction(am, viewMenu, ActionEditorSubWindow, m_contexts,
271
                      tr("Action Editor"), QLatin1String("FormEditor.ActionEditor"));
272 273 274
    // Lock/Reset
    Core::Command *cmd = addToolAction(m_editorWidget->menuSeparator1(), am, m_contexts, QLatin1String("FormEditor.SeparatorLock"), viewMenu, QString());
    cmd->setAttribute(Core::Command::CA_Hide);
275

276 277
    cmd = addToolAction(m_editorWidget->toggleLockedAction(), am, m_contexts, QLatin1String("FormEditor.Locked"), viewMenu, QString());
    cmd->setAttribute(Core::Command::CA_Hide);
278

279 280
    cmd = addToolAction(m_editorWidget->menuSeparator2(), am, m_contexts, QLatin1String("FormEditor.SeparatorReset"), viewMenu, QString());
    cmd->setAttribute(Core::Command::CA_Hide);
281

282 283 284
    cmd = addToolAction(m_editorWidget->resetLayoutAction(), am, m_contexts, QLatin1String("FormEditor.ResetToDefaultLayout"), viewMenu, QString());
    connect(m_editorWidget, SIGNAL(resetLayout()), m_editorWidget, SLOT(resetToDefaultLayout()));
    cmd->setAttribute(Core::Command::CA_Hide);
con's avatar
con committed
285 286 287 288
}

void FormEditorW::fullInit()
{
hjk's avatar
hjk committed
289
    QTC_ASSERT(m_initStage == RegisterPlugins, return);
con's avatar
con committed
290
    QTime *initTime = 0;
291
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
292 293 294 295 296 297 298 299
        initTime = new QTime;
        initTime->start();
    }

    QDesignerComponents::createTaskMenu(m_formeditor, parent());
    QDesignerComponents::initializePlugins(designerEditor());
    QDesignerComponents::initializeResources();
    initDesignerSubWindows();
300
    m_integration = new QtCreatorIntegration(m_formeditor, this);
con's avatar
con committed
301
    m_formeditor->setIntegration(m_integration);
302
    // Connect Qt Designer help request to HelpManager.
kh1's avatar
kh1 committed
303 304
    connect(m_integration, SIGNAL(creatorHelpRequested(QUrl)),
        Core::HelpManager::instance(), SIGNAL(helpRequested(QUrl)));
con's avatar
con committed
305 306 307 308 309

    /**
     * This will initialize our TabOrder, Signals and slots and Buddy editors.
     */
    QList<QObject*> plugins = QPluginLoader::staticInstances();
310 311 312
#if QT_VERSION >= 0x050000
    plugins += m_formeditor->pluginInstances();
#else
con's avatar
con committed
313
    plugins += m_formeditor->pluginManager()->instances();
314
#endif
con's avatar
con committed
315 316 317 318 319 320 321
    foreach (QObject *plugin, plugins) {
        if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
            if (!formEditorPlugin->isInitialized())
                formEditorPlugin->initialize(m_formeditor);
        }
    }

322 323 324
    if (m_actionAboutPlugins)
        m_actionAboutPlugins->setEnabled(true);

325
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
326 327 328
        qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
        delete initTime;
    }
329

Lasse Holmstedt's avatar
Lasse Holmstedt committed
330 331
    connect(m_core->editorManager()->instance(), SIGNAL(editorsClosed(QList<Core::IEditor*>)),
            SLOT(closeFormEditorsForXmlEditors(QList<Core::IEditor*>)));
332 333 334 335 336 337
    // Nest toolbar and editor widget
    m_editorWidget = new EditorWidget(this);
    QSettings *settings = m_core->settings();
    settings->beginGroup(settingsGroup);
    m_editorWidget->restoreSettings(settings);
    settings->endGroup();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
338

Lasse Holmstedt's avatar
Lasse Holmstedt committed
339 340
    m_editorToolBar = createEditorToolBar();
    m_toolBar = Core::EditorManager::createToolBar();
341
    m_toolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
342 343 344
    m_toolBar->setNavigationVisible(false);
    m_toolBar->addCenterToolBar(m_editorToolBar);

345
    m_designMode = Core::DesignMode::instance();
346 347 348 349 350
    m_modeWidget = new QWidget;
    m_modeWidget->setObjectName(QLatin1String("DesignerModeWidget"));
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->setSpacing(0);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
351
    layout->addWidget(m_toolBar);
352 353 354 355
    // Avoid mode switch to 'Edit' mode when the application started by
    // 'Run' in 'Design' mode emits output.
    Core::MiniSplitter *splitter = new Core::MiniSplitter(Qt::Vertical);
    splitter->addWidget(m_editorWidget);
356 357 358
    QWidget *outputPane = new Core::OutputPanePlaceHolder(m_designMode, splitter);
    outputPane->setObjectName(QLatin1String("DesignerOutputPanePlaceHolder"));
    splitter->addWidget(outputPane);
359
    layout->addWidget(splitter);
360 361
    m_modeWidget->setLayout(layout);

362
    Core::Context designerContexts = m_contexts;
363
    designerContexts.add(Core::Constants::C_EDITORMANAGER);
364
    m_context = new DesignerContext(designerContexts, m_modeWidget, this);
365 366
    m_core->addContextObject(m_context);

367
    m_designMode->registerDesignWidget(m_modeWidget, QStringList(QLatin1String(FORM_MIMETYPE)), m_contexts);
368 369

    setupViewActions();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
370

con's avatar
con committed
371 372 373 374 375 376 377 378
    m_initStage = FullyInitialized;
}

void FormEditorW::initDesignerSubWindows()
{
    qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount, static_cast<QWidget*>(0));

    QDesignerWidgetBoxInterface *wb = QDesignerComponents::createWidgetBox(m_formeditor, 0);
con's avatar
con committed
379
    wb->setWindowTitle(tr("Widget Box"));
380
    wb->setObjectName(QLatin1String("WidgetBox"));
con's avatar
con committed
381 382 383 384
    m_formeditor->setWidgetBox(wb);
    m_designerSubWindows[WidgetBoxSubWindow] = wb;

    QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, 0);
con's avatar
con committed
385
    oi->setWindowTitle(tr("Object Inspector"));
386
    oi->setObjectName(QLatin1String("ObjectInspector"));
con's avatar
con committed
387 388 389 390
    m_formeditor->setObjectInspector(oi);
    m_designerSubWindows[ObjectInspectorSubWindow] = oi;

    QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, 0);
con's avatar
con committed
391
    pe->setWindowTitle(tr("Property Editor"));
392
    pe->setObjectName(QLatin1String("PropertyEditor"));
con's avatar
con committed
393 394 395 396
    m_formeditor->setPropertyEditor(pe);
    m_designerSubWindows[PropertyEditorSubWindow] = pe;

    QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, 0);
Daniel Molkentin's avatar
Daniel Molkentin committed
397
    se->setWindowTitle(tr("Signals && Slots Editor"));
398
    se->setObjectName(QLatin1String("SignalsAndSlotsEditor"));
con's avatar
con committed
399 400 401
    m_designerSubWindows[SignalSlotEditorSubWindow] = se;

    QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, 0);
con's avatar
con committed
402
    ae->setWindowTitle(tr("Action Editor"));
403
    ae->setObjectName(QLatin1String("ActionEditor"));
con's avatar
con committed
404 405 406 407
    m_formeditor->setActionEditor(ae);
    m_designerSubWindows[ActionEditorSubWindow] = ae;
}

408 409 410 411 412
QList<Core::IOptionsPage *> FormEditorW::optionsPages() const
{
    return m_settingsPages;
}

con's avatar
con committed
413 414
void FormEditorW::ensureInitStage(InitializationStage s)
{
415
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
        qDebug() << Q_FUNC_INFO << s;
    if (!m_self)
        m_self = new FormEditorW;
    if (m_self->m_initStage >= s)
        return;
    QApplication::setOverrideCursor(Qt::WaitCursor);
    m_self->fullInit();
    QApplication::restoreOverrideCursor();
}

FormEditorW *FormEditorW::instance()
{
    ensureInitStage(FullyInitialized);
    return m_self;
}

void FormEditorW::deleteInstance()
{
    delete m_self;
}

void FormEditorW::setupActions()
{
439
    Core::ActionManager *am = m_core->actionManager();
con's avatar
con committed
440
    Core::Command *command;
con's avatar
con committed
441 442

    //menus
443
    Core::ActionContainer *medit =
con's avatar
con committed
444
        am->actionContainer(Core::Constants::M_EDIT);
445
    Core::ActionContainer *mtools =
con's avatar
con committed
446 447
        am->actionContainer(Core::Constants::M_TOOLS);

448
    Core::ActionContainer *mformtools =
con's avatar
con committed
449
        am->createMenu(M_FORMEDITOR);
Friedemann Kleint's avatar
Friedemann Kleint committed
450
    mformtools->menu()->setTitle(tr("For&m Editor"));
con's avatar
con committed
451 452 453
    mtools->addMenu(mformtools);

    //overridden actions
454 455 456 457 458 459
    bindShortcut(am->registerAction(m_fwm->actionUndo(), Core::Constants::UNDO, m_contexts), m_fwm->actionUndo());
    bindShortcut(am->registerAction(m_fwm->actionRedo(), Core::Constants::REDO, m_contexts), m_fwm->actionRedo());
    bindShortcut(am->registerAction(m_fwm->actionCut(), Core::Constants::CUT, m_contexts), m_fwm->actionCut());
    bindShortcut(am->registerAction(m_fwm->actionCopy(), Core::Constants::COPY, m_contexts), m_fwm->actionCopy());
    bindShortcut(am->registerAction(m_fwm->actionPaste(), Core::Constants::PASTE, m_contexts), m_fwm->actionPaste());
    bindShortcut(am->registerAction(m_fwm->actionSelectAll(), Core::Constants::SELECTALL, m_contexts), m_fwm->actionSelectAll());
con's avatar
con committed
460 461

    m_actionPrint = new QAction(this);
462
    bindShortcut(am->registerAction(m_actionPrint, Core::Constants::PRINT, m_contexts), m_actionPrint);
con's avatar
con committed
463 464
    connect(m_actionPrint, SIGNAL(triggered()), this, SLOT(print()));

465 466 467
    //'delete' action. Do not set a shortcut as Designer handles
    // the 'Delete' key by event filter. Setting a shortcut triggers
    // buggy behaviour on Mac (Pressing Delete in QLineEdit removing the widget).
hjk's avatar
hjk committed
468
    command = am->registerAction(m_fwm->actionDelete(), Core::Id("FormEditor.Edit.Delete"), m_contexts);
469
    bindShortcut(command, m_fwm->actionDelete());
con's avatar
con committed
470
    command->setAttribute(Core::Command::CA_Hide);
con's avatar
con committed
471 472 473 474 475 476
    medit->addAction(command, Core::Constants::G_EDIT_COPYPASTE);

    m_actionGroupEditMode = new QActionGroup(this);
    m_actionGroupEditMode->setExclusive(true);
    connect(m_actionGroupEditMode, SIGNAL(triggered(QAction*)), this, SLOT(activateEditMode(QAction*)));

con's avatar
con committed
477 478
    m_modeActionSeparator = new QAction(this);
    m_modeActionSeparator->setSeparator(true);
hjk's avatar
hjk committed
479
    command = am->registerAction(m_modeActionSeparator, Core::Id("FormEditor.Sep.ModeActions"), m_contexts);
con's avatar
con committed
480 481
    medit->addAction(command, Core::Constants::G_EDIT_OTHER);

con's avatar
con committed
482
    m_toolActionIds.push_back(QLatin1String("FormEditor.WidgetEditor"));
483
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
484
                         tr("Edit Widgets"), m_toolActionIds.back(),
con's avatar
con committed
485 486 487
                         EditModeWidgetEditor, QLatin1String("widgettool.png"), tr("F3"));

    m_toolActionIds.push_back(QLatin1String("FormEditor.SignalsSlotsEditor"));
488
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
489
                         tr("Edit Signals/Slots"), m_toolActionIds.back(),
con's avatar
con committed
490 491 492
                         EditModeSignalsSlotEditor, QLatin1String("signalslottool.png"), tr("F4"));

    m_toolActionIds.push_back(QLatin1String("FormEditor.BuddyEditor"));
493
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
494
                         tr("Edit Buddies"), m_toolActionIds.back(),
con's avatar
con committed
495 496 497
                         EditModeBuddyEditor, QLatin1String("buddytool.png"));

    m_toolActionIds.push_back(QLatin1String("FormEditor.TabOrderEditor"));
498
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
499
                         tr("Edit Tab Order"),  m_toolActionIds.back(),
con's avatar
con committed
500 501 502 503
                         EditModeTabOrderEditor, QLatin1String("tabordertool.png"));

    //tool actions
    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutHorizontally"));
504
    const QString horizLayoutShortcut = osMac ? tr("Meta+H") : tr("Ctrl+H");
505
    addToolAction(m_fwm->actionHorizontalLayout(), am, m_contexts,
506 507
                  m_toolActionIds.back(), mformtools, horizLayoutShortcut);

con's avatar
con committed
508
    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutVertically"));
509
    const QString vertLayoutShortcut = osMac ? tr("Meta+L") : tr("Ctrl+L");
510
    addToolAction(m_fwm->actionVerticalLayout(), am, m_contexts,
511
                  m_toolActionIds.back(),  mformtools, vertLayoutShortcut);
con's avatar
con committed
512 513

    m_toolActionIds.push_back(QLatin1String("FormEditor.SplitHorizontal"));
514
    addToolAction(m_fwm->actionSplitHorizontal(), am, m_contexts,
con's avatar
con committed
515 516 517
                  m_toolActionIds.back(), mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.SplitVertical"));
518
    addToolAction(m_fwm->actionSplitVertical(), am, m_contexts,
con's avatar
con committed
519 520 521
                  m_toolActionIds.back(), mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutForm"));
522
    addToolAction(m_fwm->actionFormLayout(), am, m_contexts,
con's avatar
con committed
523 524 525
                  m_toolActionIds.back(),  mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutGrid"));
526
    const QString gridShortcut = osMac ? tr("Meta+G") : tr("Ctrl+G");
527
    addToolAction(m_fwm->actionGridLayout(), am, m_contexts,
528
                  m_toolActionIds.back(),  mformtools, gridShortcut);
con's avatar
con committed
529 530

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutBreak"));
531
    addToolAction(m_fwm->actionBreakLayout(), am, m_contexts,
con's avatar
con committed
532 533 534
                  m_toolActionIds.back(), mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutAdjustSize"));
535
    const QString adjustShortcut = osMac ? tr("Meta+J") : tr("Ctrl+J");
536
    addToolAction(m_fwm->actionAdjustSize(), am, m_contexts,
537
                  m_toolActionIds.back(),  mformtools, adjustShortcut);
con's avatar
con committed
538 539

    m_toolActionIds.push_back(QLatin1String("FormEditor.SimplifyLayout"));
540
    addToolAction(m_fwm->actionSimplifyLayout(), am, m_contexts,
con's avatar
con committed
541 542
                  m_toolActionIds.back(),  mformtools);

543
    createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator1"));
con's avatar
con committed
544

545
    addToolAction(m_fwm->actionLower(), am, m_contexts,
con's avatar
con committed
546 547
                  QLatin1String("FormEditor.Lower"), mformtools);

548
    addToolAction(m_fwm->actionRaise(), am, m_contexts,
con's avatar
con committed
549 550 551
                  QLatin1String("FormEditor.Raise"), mformtools);

    // Commands that do not go into the editor toolbar
552
    createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator2"));
con's avatar
con committed
553

554 555 556
#if QT_VERSION >= 0x050000
    m_actionPreview = m_fwm->action(QDesignerFormWindowManagerInterface::DefaultPreviewAction);
#else
con's avatar
con committed
557
    m_actionPreview = m_fwm->actionDefaultPreview();
558
#endif
hjk's avatar
hjk committed
559
    QTC_ASSERT(m_actionPreview, return);
560
    addToolAction(m_actionPreview,  am,  m_contexts,
561
                   QLatin1String("FormEditor.Preview"), mformtools, tr("Alt+Shift+R"));
con's avatar
con committed
562 563

    // Preview in style...
564 565 566
#if QT_VERSION >= 0x050000
    m_actionGroupPreviewInStyle = m_fwm->actionGroup(QDesignerFormWindowManagerInterface::StyledPreviewActionGroup);
#else
con's avatar
con committed
567
    m_actionGroupPreviewInStyle = m_fwm->actionGroupPreviewInStyle();
568 569
#endif

570 571 572 573
    Core::ActionContainer *previewAC = createPreviewStyleMenu(am, m_actionGroupPreviewInStyle);
    m_previewInStyleMenu = previewAC->menu();
    mformtools->addMenu(previewAC);
    setPreviewMenuEnabled(false);
con's avatar
con committed
574 575

    // Form settings
576
    createSeparator(this, am, m_contexts,  medit, QLatin1String("FormEditor.Edit.Separator2"), Core::Constants::G_EDIT_OTHER);
con's avatar
con committed
577

578
    createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator3"));
579 580 581 582 583 584 585 586 587 588 589

    m_actionSwitchSource = new QAction(tr("Switch Source/Form"), this);
    connect(m_actionSwitchSource, SIGNAL(triggered()), this, SLOT(switchSourceForm()));

    // Switch form/source in editor/design contexts.
    Core::Context switchContexts = m_contexts;
    switchContexts.add(Core::Constants::C_EDITORMANAGER);
    addToolAction(m_actionSwitchSource, am, switchContexts, QLatin1String("FormEditor.FormSwitchSource"), mformtools,
                  tr("Shift+F4"));

    createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator4"));
590 591 592
#if QT_VERSION >= 0x050000
    QAction *actionFormSettings = m_fwm->action(QDesignerFormWindowManagerInterface::FormWindowSettingsDialogAction);
#else
con's avatar
con committed
593
    QAction *actionFormSettings = m_fwm->actionShowFormWindowSettingsDialog();
594
#endif
595
    addToolAction(actionFormSettings, am, m_contexts, QLatin1String("FormEditor.FormSettings"), mformtools);
596

597
    createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator5"));
598
    m_actionAboutPlugins = new QAction(tr("About Qt Designer plugins...."), this);
599
    addToolAction(m_actionAboutPlugins,  am,  m_contexts,
600
                   QLatin1String("FormEditor.AboutPlugins"), mformtools);
601 602 603 604 605 606 607
    connect(m_actionAboutPlugins,  SIGNAL(triggered()), m_fwm,
#if QT_VERSION >= 0x050000
            SLOT(showPluginDialog())
#else
            SLOT(aboutPlugins())
#endif
            );
608 609
    m_actionAboutPlugins->setEnabled(false);

con's avatar
con committed
610 611 612 613 614 615
    // FWM
    connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface *)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface *)));
}

QToolBar *FormEditorW::createEditorToolBar() const
{
616
    QToolBar *editorToolBar = new QToolBar;
617
    Core::ActionManager *am = m_core->actionManager();
con's avatar
con committed
618 619
    const QStringList::const_iterator cend = m_toolActionIds.constEnd();
    for (QStringList::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
con's avatar
con committed
620
        Core::Command *cmd = am->command(*it);
hjk's avatar
hjk committed
621
        QTC_ASSERT(cmd, continue);
con's avatar
con committed
622 623
        QAction *action = cmd->action();
        if (!action->icon().isNull()) // Simplify grid has no action yet
624
            editorToolBar->addAction(action);
con's avatar
con committed
625
    }
626 627 628 629
    const int size = editorToolBar->style()->pixelMetric(QStyle::PM_SmallIconSize);
    editorToolBar->setIconSize(QSize(size, size));
    editorToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    return editorToolBar;
con's avatar
con committed
630 631
}

632
Core::ActionContainer *FormEditorW::createPreviewStyleMenu(Core::ActionManager *am,
con's avatar
con committed
633 634 635
                                                            QActionGroup *actionGroup)
{
    const QString menuId = QLatin1String(M_FORMEDITOR_PREVIEW);
636
    Core::ActionContainer *menuPreviewStyle = am->createMenu(menuId);
con's avatar
con committed
637 638 639 640 641 642 643 644 645 646 647
    menuPreviewStyle->menu()->setTitle(tr("Preview in"));

    // The preview menu is a list of invisible actions for the embedded design
    // device profiles (integer data) followed by a separator and the styles
    // (string data). Make device profiles update their text and hide them
    // in the configuration dialog.
    const QList<QAction*> actions = actionGroup->actions();

    const QString deviceProfilePrefix = QLatin1String("DeviceProfile");
    const QChar dot = QLatin1Char('.');

hjk's avatar
hjk committed
648
    foreach (QAction* a, actions) {
con's avatar
con committed
649 650 651 652 653 654 655 656 657
        QString name = menuId;
        name += dot;
        const QVariant data = a->data();
        const bool isDeviceProfile = data.type() == QVariant::Int;
        if (isDeviceProfile) {
            name += deviceProfilePrefix;
            name += dot;
        }
        name += data.toString();
658
        Core::Command *command = am->registerAction(a, name, m_contexts);
659
        bindShortcut(command, a);
con's avatar
con committed
660
        if (isDeviceProfile) {
con's avatar
con committed
661
            command->setAttribute(Core::Command::CA_UpdateText);
662
            command->setAttribute(Core::Command::CA_NonConfigurable);
con's avatar
con committed
663 664 665 666 667 668
        }
        menuPreviewStyle->addAction(command);
    }
    return menuPreviewStyle;
}

669 670 671 672 673 674
void FormEditorW::setPreviewMenuEnabled(bool e)
{
    m_actionPreview->setEnabled(e);
    m_previewInStyleMenu->setEnabled(e);
}

con's avatar
con committed
675 676 677
void FormEditorW::saveSettings(QSettings *s)
{
    s->beginGroup(settingsGroup);
678
    m_editorWidget->saveSettings(s);
679
    s->endGroup();
con's avatar
con committed
680 681 682 683 684 685 686
}

void FormEditorW::critical(const QString &errorMessage)
{
    QMessageBox::critical(m_core->mainWindow(), tr("Designer"),  errorMessage);
}

687 688 689 690 691 692 693 694 695 696 697 698
// Apply the command shortcut to the action and connects to the command's keySequenceChanged signal
void FormEditorW::bindShortcut(Core::Command *command, QAction *action)
{
    m_commandToDesignerAction.insert(command, action);
    connect(command, SIGNAL(keySequenceChanged()),
            m_shortcutMapper, SLOT(map()));
    m_shortcutMapper->setMapping(command, command);
    updateShortcut(command);
}

// Create an action to activate a designer tool
QAction *FormEditorW::createEditModeAction(QActionGroup *ag,
699
                                     const Core::Context &context,
700 701 702 703 704 705 706 707 708 709 710 711 712
                                     Core::ActionManager *am,
                                     Core::ActionContainer *medit,
                                     const QString &actionName,
                                     const QString &name,
                                     int toolNumber,
                                     const QString &iconName,
                                     const QString &keySequence)
{
    QAction *rc = new QAction(actionName, ag);
    rc->setCheckable(true);
    if (!iconName.isEmpty())
         rc->setIcon(designerIcon(iconName));
    Core::Command *command = am->registerAction(rc, name, context);
713
    command->setAttribute(Core::Command::CA_Hide);
714 715 716 717 718 719 720 721 722 723
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
    bindShortcut(command, rc);
    medit->addAction(command, Core::Constants::G_EDIT_OTHER);
    rc->setData(toolNumber);
    ag->addAction(rc);
    return rc;
}

// Create a tool action
724
Core::Command *FormEditorW::addToolAction(QAction *a, Core::ActionManager *am,
725
                                          const Core::Context &context, const QString &name,
726
                                          Core::ActionContainer *c1, const QString &keySequence)
727 728 729 730
{
    Core::Command *command = am->registerAction(a, name, context);
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
731 732
    if (!a->isSeparator())
        bindShortcut(command, a);
733
    c1->addAction(command);
734
    return command;
735 736
}

737
EditorData FormEditorW::createEditor(QWidget *parent)
con's avatar
con committed
738
{
739 740 741 742
    if (Designer::Constants::Internal::debug)
        qDebug() << "FormEditorW::createEditor";
    // Create and associate form and text editor.
    EditorData data;
con's avatar
con committed
743
    m_fwm->closeAllPreviews();
744 745 746
#if QT_VERSION >= 0x050000
    QDesignerFormWindowInterface *form = m_fwm->createFormWindow(0);
#else
747
    qdesigner_internal::FormWindowBase *form = qobject_cast<qdesigner_internal::FormWindowBase *>(m_fwm->createFormWindow(0));
748
#endif
749
    QTC_ASSERT(form, return data);
con's avatar
con committed
750
    connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int)));
751
    ResourceHandler *resourceHandler = new ResourceHandler(form);
752
#if QT_VERSION < 0x050000
753
    form->setDesignerGrid(qdesigner_internal::FormWindowBase::defaultDesignerGrid());
con's avatar
con committed
754
    qdesigner_internal::FormWindowBase::setupDefaultAction(form);
755
#endif
756
    data.widgetHost = new SharedTools::WidgetHost( /* parent */ 0, form);
757 758
    DesignerXmlEditor *xmlEditor = new DesignerXmlEditor(form, parent);
    TextEditor::TextEditorSettings::instance()->initializeEditor(xmlEditor);
759 760
    data.formWindowEditor = xmlEditor->designerEditor();
    connect(data.widgetHost, SIGNAL(formWindowSizeChanged(int,int)),
761
            xmlEditor, SIGNAL(changed()));
762
    connect(data.formWindowEditor->file(), SIGNAL(changed()),
763
            resourceHandler, SLOT(updateResources()));
764
    m_editorWidget->add(data);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
765

766
    m_toolBar->addEditor(xmlEditor->editor());
Lasse Holmstedt's avatar
Lasse Holmstedt committed
767

768
    return data;
con's avatar
con committed
769 770
}

771 772 773 774 775 776 777 778 779 780 781
void FormEditorW::updateShortcut(QObject *command)
{
    Core::Command *c = qobject_cast<Core::Command *>(command);
    if (!c)
        return;
    QAction *a = m_commandToDesignerAction.value(c);
    if (!a)
        return;
    a->setShortcut(c->action()->shortcut());
}

con's avatar
con committed
782 783
void FormEditorW::currentEditorChanged(Core::IEditor *editor)
{
784 785
    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
con's avatar
con committed
786

Lasse Holmstedt's avatar
Lasse Holmstedt committed
787
    if (editor && editor->id() == QLatin1String(Constants::K_DESIGNER_XML_EDITOR_ID)) {
788
        FormWindowEditor *xmlEditor = qobject_cast<FormWindowEditor *>(editor);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
789
        QTC_ASSERT(xmlEditor, return);
790
        ensureInitStage(FullyInitialized);
791
        SharedTools::WidgetHost *fw = m_editorWidget->formWindowEditorForXmlEditor(xmlEditor);
792 793
        QTC_ASSERT(fw, return)
        m_editorWidget->setVisibleEditor(xmlEditor);
con's avatar
con committed
794 795 796 797 798 799
        m_fwm->setActiveFormWindow(fw->formWindow());
    }
}

void FormEditorW::activeFormWindowChanged(QDesignerFormWindowInterface *afw)
{
800
    if (Designer::Constants::Internal::debug)
801
        qDebug() << Q_FUNC_INFO << afw << " of " << m_fwm->formWindowCount();
con's avatar
con committed
802 803

    m_fwm->closeAllPreviews();
804
    setPreviewMenuEnabled(afw != 0);
con's avatar
con committed
805 806
}

807
EditorData FormEditorW::activeEditor() const
con's avatar
con committed
808
{
809
    if (m_editorWidget)
810 811
        return m_editorWidget->activeEditor();
    return EditorData();
con's avatar
con committed
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
}

void FormEditorW::activateEditMode(int id)
{
    if (const int count = m_fwm->formWindowCount())
        for (int i = 0; i <  count; i++)
             m_fwm->formWindow(i)->setCurrentTool(id);
}

void FormEditorW::activateEditMode(QAction* a)
{
    activateEditMode(a->data().toInt());
}

void FormEditorW::toolChanged(int t)
{
    typedef QList<QAction *> ActionList;
    if (const QAction *currentAction = m_actionGroupEditMode->checkedAction())
        if (currentAction->data().toInt() == t)
            return;
    const ActionList actions = m_actionGroupEditMode->actions();
    const ActionList::const_iterator cend = actions.constEnd();
    for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
        if ( (*it)->data().toInt() == t) {
            (*it)->setChecked(true);
            break;
        }
}

Lasse Holmstedt's avatar
Lasse Holmstedt committed
841 842 843
void FormEditorW::closeFormEditorsForXmlEditors(QList<Core::IEditor*> editors)
{
    foreach(Core::IEditor *editor, editors) {
844
        m_editorWidget->removeFormWindowEditor(editor);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
845 846 847
    }
}

con's avatar
con committed
848 849 850 851 852 853 854 855 856 857 858 859 860
void FormEditorW::print()
{
    // Printing code courtesy of designer_actions.cpp
    QDesignerFormWindowInterface *fw = m_fwm->activeFormWindow();
    if (!fw)
        return;

    const bool oldFullPage =  m_core->printer()->fullPage();
    const QPrinter::Orientation oldOrientation =  m_core->printer()->orientation ();
    m_core->printer()->setFullPage(false);
    do {
        // Grab the image to be able to a suggest suitable orientation
        QString errorMessage;
861 862 863
#if QT_VERSION >= 0x050000
        const QPixmap pixmap = m_fwm->createPreviewPixmap();
#else
con's avatar
con committed
864
        const QPixmap pixmap = m_fwm->createPreviewPixmap(&errorMessage);
865
#endif
con's avatar
con committed
866
        if (pixmap.isNull()) {
Jure Repinc's avatar
Jure Repinc committed
867
            critical(tr("The image could not be created: %1").arg(errorMessage));
con's avatar
con committed
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
            break;
        }

        const QSizeF pixmapSize = pixmap.size();
        m_core->printer()->setOrientation( pixmapSize.width() > pixmapSize.height() ?  QPrinter::Landscape :  QPrinter::Portrait);

        // Printer parameters
        QPrintDialog dialog(m_core->printer(), fw);
        if (!dialog.exec())
           break;

        const QCursor oldCursor = m_core->mainWindow()->cursor();
        m_core->mainWindow()->setCursor(Qt::WaitCursor);
        // Estimate of required scaling to make form look the same on screen and printer.
        const double suggestedScaling = static_cast<double>(m_core->printer()->physicalDpiX()) /  static_cast<double>(fw->physicalDpiX());

        QPainter painter(m_core->printer());
        painter.setRenderHint(QPainter::SmoothPixmapTransform);

        // Clamp to page
        const QRectF page =  painter.viewport();
        const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
        const double scaling = qMin(suggestedScaling, maxScaling);

Felix Geyer's avatar
Felix Geyer committed
892 893
        const double xOffset = page.left() + qMax(0.0, (page.size().width()  - scaling * pixmapSize.width())  / 2.0);
        const double yOffset = page.top()  + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
con's avatar
con committed
894 895 896 897 898 899 900 901 902 903 904

        // Draw.
        painter.translate(xOffset, yOffset);
        painter.scale(scaling, scaling);
        painter.drawPixmap(0, 0, pixmap);
        m_core->mainWindow()->setCursor(oldCursor);

    } while (false);
    m_core->printer()->setFullPage(oldFullPage);
    m_core->printer()->setOrientation(oldOrientation);
}
Lasse Holmstedt's avatar
Lasse Holmstedt committed
905

906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
// Find out current existing editor file
static QString currentFile(const Core::EditorManager *em)
{
    if (Core::IEditor *editor = em->currentEditor())
        if (const Core::IFile *file = editor->file()) {
            const QString fileName = file->fileName();
            if (!fileName.isEmpty() && QFileInfo(fileName).isFile())
                return fileName;
        }
    return QString();
}

// Switch between form ('ui') and source file ('cpp'):
// Find corresponding 'other' file, simply assuming it is in the same directory.
static QString otherFile(const Core::EditorManager *em)
{
    // Determine mime type of current file.
    const QString current = currentFile(em);
    if (current.isEmpty())
        return QString();
    const Core::MimeDatabase *mdb = Core::ICore::instance()->mimeDatabase();
    const Core::MimeType currentMimeType = mdb->findByFile(current);
    if (!currentMimeType)
        return QString();
    // Determine potential suffixes of candidate files
    // 'ui' -> 'cpp', 'cpp/h' -> 'ui'.
    QStringList candidateSuffixes;
    if (currentMimeType.type() == QLatin1String(FORM_MIMETYPE)) {
        candidateSuffixes += mdb->findByType(QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE)).suffixes();
    } else if (currentMimeType.type() == QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE)
               || currentMimeType.type() == QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE)) {
        candidateSuffixes += mdb->findByType(QLatin1String(FORM_MIMETYPE)).suffixes();
    } else {
        return QString();
    }
    // Try to find existing file with desired suffix
    const QFileInfo currentFI(current);
    const QString currentBaseName = currentFI.path() + QLatin1Char('/')
            + currentFI.baseName() + QLatin1Char('.');
    foreach (const QString &candidateSuffix, candidateSuffixes) {
        const QFileInfo fi(currentBaseName + candidateSuffix);
        if (fi.isFile())
            return fi.absoluteFilePath();
    }
    return QString();
}

void FormEditorW::switchSourceForm()
{
    Core::EditorManager *em = Core::EditorManager::instance();
    const QString fileToOpen = otherFile(em);
    if (!fileToOpen.isEmpty())
958
        em->openEditor(fileToOpen, QString(), Core::EditorManager::ModeSwitch);
959 960
}

961 962
} // namespace Internal
} // namespace Designer