formeditorw.cpp 33.5 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11 12 13 14
** 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.
15
**
16
** GNU Lesser General Public License Usage
17
**
18 19 20 21 22 23
** 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.
24
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
hjk's avatar
hjk committed
29

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

44
#include <coreplugin/editortoolbar.h>
Lasse Holmstedt's avatar
Lasse Holmstedt committed
45
#include <coreplugin/designmode.h>
con's avatar
con committed
46
#include <coreplugin/coreconstants.h>
47
#include <coreplugin/icore.h>
kh1's avatar
kh1 committed
48
#include <coreplugin/helpmanager.h>
con's avatar
con committed
49
#include <coreplugin/uniqueidmanager.h>
50
#include <coreplugin/actionmanager/actionmanager.h>
51 52
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
con's avatar
con committed
53
#include <coreplugin/editormanager/editormanager.h>
54 55
#include <coreplugin/minisplitter.h>
#include <coreplugin/outputpane.h>
56
#include <texteditor/texteditorsettings.h>
57
#include <extensionsystem/pluginmanager.h>
hjk's avatar
hjk committed
58
#include <utils/qtcassert.h>
con's avatar
con committed
59 60

#include <QtDesigner/QDesignerFormEditorPluginInterface>
Roberto Raggi's avatar
Roberto Raggi committed
61
#include "qt_private/pluginmanager_p.h"
con's avatar
con committed
62

Roberto Raggi's avatar
Roberto Raggi committed
63 64 65
#include "qt_private/iconloader_p.h"  // createIconSet
#include "qt_private/qdesigner_formwindowmanager_p.h"
#include "qt_private/formwindowbase_p.h"
con's avatar
con committed
66 67 68 69 70 71 72
#include <QtDesigner/QDesignerFormEditorInterface>
#include <QtDesigner/QDesignerComponents>

#include <QtDesigner/QDesignerWidgetBoxInterface>
#include <QtDesigner/abstractobjectinspector.h>
#include <QtDesigner/QDesignerPropertyEditorInterface>
#include <QtDesigner/QDesignerActionEditorInterface>
73
#include <QtDesigner/QDesignerFormEditorInterface>
con's avatar
con committed
74 75 76 77 78

#include <QtGui/QAction>
#include <QtGui/QActionGroup>
#include <QtGui/QApplication>
#include <QtGui/QCursor>
con's avatar
con committed
79
#include <QtGui/QDockWidget>
con's avatar
con committed
80 81 82 83 84 85 86 87 88
#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>
89
#include <QtGui/QVBoxLayout>
con's avatar
con committed
90 91 92

#include <QtCore/QDebug>
#include <QtCore/QSettings>
93 94 95
#include <QtCore/QSignalMapper>
#include <QtCore/QPluginLoader>
#include <QtCore/QTime>
con's avatar
con committed
96

97
static const char settingsGroup[] = "Designer";
con's avatar
con committed
98

99 100 101 102 103 104 105 106
#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
107
 * "edit mode" context) when it is focused.
108 109 110 111 112
 * 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
113 114 115 116 117 118 119 120
static inline QIcon designerIcon(const QString &iconName)
{
    const QIcon icon = qdesigner_internal::createIconSet(iconName);
    if (icon.isNull())
        qWarning() << "Unable to locate " << iconName;
    return icon;
}

121 122
// Create a menu separator
static inline QAction *createSeparator(QObject *parent,
123
                                 Core::ActionManager *am,
con's avatar
con committed
124
                                 const QList<int> &context,
125
                                 Core::ActionContainer *container,
con's avatar
con committed
126 127 128 129 130
                                 const QString &name = QString(),
                                 const QString &group = QString())
{
    QAction *actSeparator = new QAction(parent);
    actSeparator->setSeparator(true);
con's avatar
con committed
131
    Core::Command *command = am->registerAction(actSeparator, name, context);
con's avatar
con committed
132 133 134 135 136 137
    container->addAction(command, group);
    return actSeparator;
}

using namespace Designer::Constants;

138 139
namespace Designer {
namespace Internal {
con's avatar
con committed
140 141 142

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

con's avatar
con committed
143 144 145 146 147 148
FormEditorW *FormEditorW::m_self = 0;

FormEditorW::FormEditorW() :
    m_formeditor(QDesignerComponents::createFormEditor(0)),
    m_integration(0),
    m_fwm(0),
149
    m_core(Core::ICore::instance()),
con's avatar
con committed
150 151
    m_initStage(RegisterPlugins),
    m_actionGroupEditMode(0),
152 153 154
    m_actionPrint(0),
    m_actionPreview(0),
    m_actionGroupPreviewInStyle(0),
155
    m_actionAboutPlugins(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
156 157
    m_shortcutMapper(new QSignalMapper(this)),
    m_context(0),
158 159
    m_modeWidget(0),
    m_editorWidget(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
160 161 162
    m_designMode(0),
    m_editorToolBar(0),
    m_toolBar(0)
con's avatar
con committed
163
{
164
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
165
        qDebug() << Q_FUNC_INFO;
hjk's avatar
hjk committed
166
    QTC_ASSERT(!m_self, return);
con's avatar
con committed
167
    m_self = this;
hjk's avatar
hjk committed
168
    QTC_ASSERT(m_core, return);
con's avatar
con committed
169 170 171 172 173 174 175 176

    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());

    m_fwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager*>(m_formeditor->formWindowManager());
hjk's avatar
hjk committed
177
    QTC_ASSERT(m_fwm, return);
con's avatar
con committed
178

179
    Core::UniqueIDManager *idMan = Core::UniqueIDManager::instance();
180
    m_contexts << idMan->uniqueIdentifier(QLatin1String(Designer::Constants::C_FORMEDITOR));
181

con's avatar
con committed
182 183 184 185 186 187 188 189 190 191
    setupActions();

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

    connect(m_core->editorManager(), SIGNAL(currentEditorChanged(Core::IEditor *)),
            this, SLOT(currentEditorChanged(Core::IEditor *)));
192 193
    connect(m_shortcutMapper, SIGNAL(mapped(QObject *)),
            this, SLOT(updateShortcut(QObject *)));
con's avatar
con committed
194 195 196 197
}

FormEditorW::~FormEditorW()
{
198 199
    if (m_context)
        m_core->removeContextObject(m_context);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
200
    if (m_initStage == FullyInitialized) {
201 202 203 204 205
        if (QSettings *s = m_core->settings()) {
            m_core->settings()->beginGroup(settingsGroup);
            m_editorWidget->saveSettings(s);
            s->endGroup();
        }
Lasse Holmstedt's avatar
Lasse Holmstedt committed
206

207 208 209 210
        m_designMode->unregisterDesignWidget(m_modeWidget);
        delete m_modeWidget;
        m_modeWidget = 0;
    }
con's avatar
con committed
211 212 213 214 215 216

    delete m_formeditor;
    foreach (SettingsPage *settingsPage, m_settingsPages) {
        ExtensionSystem::PluginManager::instance()->removeObject(settingsPage);
        delete settingsPage;
    }
Lasse Holmstedt's avatar
Lasse Holmstedt committed
217 218
    delete m_integration;

219 220 221
    m_self = 0;
}

222
// Add an actioon to toggle the view state of a dock window
223
void FormEditorW::addDockViewAction(Core::ActionManager *am,
224
                                    Core::ActionContainer *viewMenu,
225 226 227 228 229 230
                                    int index, const QList<int> &context,
                                    const QString &title, const QString &id)
{
    if (const QDockWidget *dw = m_editorWidget->designerDockWidgets()[index]) {
        QAction *action = dw->toggleViewAction();
        action->setText(title);
231 232
        Core::Command *cmd = addToolAction(action, am, context, id, viewMenu, QString());
        cmd->setAttribute(Core::Command::CA_Hide);
233 234 235 236 237 238 239
    }
}

void FormEditorW::setupViewActions()
{
    // Populate "View" menu of form editor menu
    Core::ActionManager *am = m_core->actionManager();
240 241
    Core::ActionContainer *viewMenu = am->actionContainer(QLatin1String(Core::Constants::M_WINDOW_VIEWS));
    QTC_ASSERT(viewMenu, return)
242

243
    addDockViewAction(am, viewMenu, WidgetBoxSubWindow, m_contexts,
244
                      tr("Widget box"), QLatin1String("FormEditor.WidgetBox"));
Lasse Holmstedt's avatar
Lasse Holmstedt committed
245

246
    addDockViewAction(am, viewMenu, ObjectInspectorSubWindow, m_contexts,
247
                      tr("Object Inspector"), QLatin1String("FormEditor.ObjectInspector"));
Lasse Holmstedt's avatar
Lasse Holmstedt committed
248

249
    addDockViewAction(am, viewMenu, PropertyEditorSubWindow, m_contexts,
250 251
                      tr("Property Editor"), QLatin1String("FormEditor.PropertyEditor"));

252
    addDockViewAction(am, viewMenu, SignalSlotEditorSubWindow, m_contexts,
253 254
                      tr("Signals && Slots Editor"), QLatin1String("FormEditor.SignalsAndSlotsEditor"));

255
    addDockViewAction(am, viewMenu, ActionEditorSubWindow, m_contexts,
256
                      tr("Action Editor"), QLatin1String("FormEditor.ActionEditor"));
257 258 259
    // Lock/Reset
    Core::Command *cmd = addToolAction(m_editorWidget->menuSeparator1(), am, m_contexts, QLatin1String("FormEditor.SeparatorLock"), viewMenu, QString());
    cmd->setAttribute(Core::Command::CA_Hide);
260

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

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

267 268 269
    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
270 271 272 273
}

void FormEditorW::fullInit()
{
hjk's avatar
hjk committed
274
    QTC_ASSERT(m_initStage == RegisterPlugins, return);
con's avatar
con committed
275
    QTime *initTime = 0;
276
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
277 278 279 280 281 282 283 284
        initTime = new QTime;
        initTime->start();
    }

    QDesignerComponents::createTaskMenu(m_formeditor, parent());
    QDesignerComponents::initializePlugins(designerEditor());
    QDesignerComponents::initializeResources();
    initDesignerSubWindows();
285
    m_integration = new QtCreatorIntegration(m_formeditor, this);
con's avatar
con committed
286
    m_formeditor->setIntegration(m_integration);
287
    // Connect Qt Designer help request to HelpManager.
kh1's avatar
kh1 committed
288 289
    connect(m_integration, SIGNAL(creatorHelpRequested(QUrl)),
        Core::HelpManager::instance(), SIGNAL(helpRequested(QUrl)));
con's avatar
con committed
290 291 292 293 294 295 296 297 298 299 300 301 302

    /**
     * This will initialize our TabOrder, Signals and slots and Buddy editors.
     */
    QList<QObject*> plugins = QPluginLoader::staticInstances();
    plugins += m_formeditor->pluginManager()->instances();
    foreach (QObject *plugin, plugins) {
        if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
            if (!formEditorPlugin->isInitialized())
                formEditorPlugin->initialize(m_formeditor);
        }
    }

303 304 305
    if (m_actionAboutPlugins)
        m_actionAboutPlugins->setEnabled(true);

306
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
307 308 309
        qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
        delete initTime;
    }
310

Lasse Holmstedt's avatar
Lasse Holmstedt committed
311 312
    connect(m_core->editorManager()->instance(), SIGNAL(editorsClosed(QList<Core::IEditor*>)),
            SLOT(closeFormEditorsForXmlEditors(QList<Core::IEditor*>)));
313 314 315 316 317 318
    // 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
319

Lasse Holmstedt's avatar
Lasse Holmstedt committed
320 321
    m_editorToolBar = createEditorToolBar();
    m_toolBar = Core::EditorManager::createToolBar();
322
    m_toolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
323 324 325
    m_toolBar->setNavigationVisible(false);
    m_toolBar->addCenterToolBar(m_editorToolBar);

Lasse Holmstedt's avatar
Lasse Holmstedt committed
326
    m_designMode = ExtensionSystem::PluginManager::instance()->getObject<Core::DesignMode>();
327 328 329 330 331
    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
332
    layout->addWidget(m_toolBar);
333 334 335 336 337 338
    // 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);
    splitter->addWidget(new Core::OutputPanePlaceHolder(m_designMode, splitter));
    layout->addWidget(splitter);
339 340
    m_modeWidget->setLayout(layout);

341 342 343 344
    Core::UniqueIDManager *idMan = Core::UniqueIDManager::instance();
    int editorManagerContext = idMan->uniqueIdentifier(QLatin1String(Core::Constants::C_EDITORMANAGER));

    m_context = new DesignerContext(QList<int>() << m_contexts << editorManagerContext, m_modeWidget, this);
345 346
    m_core->addContextObject(m_context);

347
    m_designMode->registerDesignWidget(m_modeWidget, QStringList(QLatin1String(FORM_MIMETYPE)), m_contexts);
348 349

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

con's avatar
con committed
351 352 353 354 355 356 357 358
    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
359
    wb->setWindowTitle(tr("Widget Box"));
360
    wb->setObjectName(QLatin1String("WidgetBox"));
con's avatar
con committed
361 362 363 364
    m_formeditor->setWidgetBox(wb);
    m_designerSubWindows[WidgetBoxSubWindow] = wb;

    QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, 0);
con's avatar
con committed
365
    oi->setWindowTitle(tr("Object Inspector"));
366
    oi->setObjectName(QLatin1String("ObjectInspector"));
con's avatar
con committed
367 368 369 370
    m_formeditor->setObjectInspector(oi);
    m_designerSubWindows[ObjectInspectorSubWindow] = oi;

    QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, 0);
con's avatar
con committed
371
    pe->setWindowTitle(tr("Property Editor"));
372
    pe->setObjectName(QLatin1String("PropertyEditor"));
con's avatar
con committed
373 374 375 376
    m_formeditor->setPropertyEditor(pe);
    m_designerSubWindows[PropertyEditorSubWindow] = pe;

    QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, 0);
Daniel Molkentin's avatar
Daniel Molkentin committed
377
    se->setWindowTitle(tr("Signals && Slots Editor"));
378
    se->setObjectName(QLatin1String("SignalsAndSlotsEditor"));
con's avatar
con committed
379 380 381
    m_designerSubWindows[SignalSlotEditorSubWindow] = se;

    QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, 0);
con's avatar
con committed
382
    ae->setWindowTitle(tr("Action Editor"));
383
    ae->setObjectName(QLatin1String("ActionEditor"));
con's avatar
con committed
384 385 386 387 388 389
    m_formeditor->setActionEditor(ae);
    m_designerSubWindows[ActionEditorSubWindow] = ae;
}

void FormEditorW::ensureInitStage(InitializationStage s)
{
390
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
        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()
{
414
    Core::ActionManager *am = m_core->actionManager();
con's avatar
con committed
415
    Core::Command *command;
con's avatar
con committed
416 417

    //menus
418
    Core::ActionContainer *medit =
con's avatar
con committed
419
        am->actionContainer(Core::Constants::M_EDIT);
420
    Core::ActionContainer *mtools =
con's avatar
con committed
421 422
        am->actionContainer(Core::Constants::M_TOOLS);

423
    Core::ActionContainer *mformtools =
con's avatar
con committed
424
        am->createMenu(M_FORMEDITOR);
Friedemann Kleint's avatar
Friedemann Kleint committed
425
    mformtools->menu()->setTitle(tr("For&m Editor"));
con's avatar
con committed
426 427 428
    mtools->addMenu(mformtools);

    //overridden actions
429 430 431 432 433 434
    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
435 436

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

440 441 442
    //'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).
443
    command = am->registerAction(m_fwm->actionDelete(), QLatin1String("FormEditor.Edit.Delete"), m_contexts);
444
    bindShortcut(command, m_fwm->actionDelete());
con's avatar
con committed
445
    command->setAttribute(Core::Command::CA_Hide);
con's avatar
con committed
446 447 448 449 450 451
    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
452 453
    m_modeActionSeparator = new QAction(this);
    m_modeActionSeparator->setSeparator(true);
454
    command = am->registerAction(m_modeActionSeparator, QLatin1String("FormEditor.Sep.ModeActions"), m_contexts);
con's avatar
con committed
455 456
    medit->addAction(command, Core::Constants::G_EDIT_OTHER);

con's avatar
con committed
457
    m_toolActionIds.push_back(QLatin1String("FormEditor.WidgetEditor"));
458
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
459
                         tr("Edit Widgets"), m_toolActionIds.back(),
con's avatar
con committed
460 461 462
                         EditModeWidgetEditor, QLatin1String("widgettool.png"), tr("F3"));

    m_toolActionIds.push_back(QLatin1String("FormEditor.SignalsSlotsEditor"));
463
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
464
                         tr("Edit Signals/Slots"), m_toolActionIds.back(),
con's avatar
con committed
465 466 467
                         EditModeSignalsSlotEditor, QLatin1String("signalslottool.png"), tr("F4"));

    m_toolActionIds.push_back(QLatin1String("FormEditor.BuddyEditor"));
468
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
469
                         tr("Edit Buddies"), m_toolActionIds.back(),
con's avatar
con committed
470 471 472
                         EditModeBuddyEditor, QLatin1String("buddytool.png"));

    m_toolActionIds.push_back(QLatin1String("FormEditor.TabOrderEditor"));
473
    createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
474
                         tr("Edit Tab Order"),  m_toolActionIds.back(),
con's avatar
con committed
475 476 477 478
                         EditModeTabOrderEditor, QLatin1String("tabordertool.png"));

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

con's avatar
con committed
483
    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutVertically"));
484
    const QString vertLayoutShortcut = osMac ? tr("Meta+L") : tr("Ctrl+L");
485
    addToolAction(m_fwm->actionVerticalLayout(), am, m_contexts,
486
                  m_toolActionIds.back(),  mformtools, vertLayoutShortcut);
con's avatar
con committed
487 488

    m_toolActionIds.push_back(QLatin1String("FormEditor.SplitHorizontal"));
489
    addToolAction(m_fwm->actionSplitHorizontal(), am, m_contexts,
con's avatar
con committed
490 491 492
                  m_toolActionIds.back(), mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.SplitVertical"));
493
    addToolAction(m_fwm->actionSplitVertical(), am, m_contexts,
con's avatar
con committed
494 495 496
                  m_toolActionIds.back(), mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutForm"));
497
    addToolAction(m_fwm->actionFormLayout(), am, m_contexts,
con's avatar
con committed
498 499 500
                  m_toolActionIds.back(),  mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutGrid"));
501
    const QString gridShortcut = osMac ? tr("Meta+G") : tr("Ctrl+G");
502
    addToolAction(m_fwm->actionGridLayout(), am, m_contexts,
503
                  m_toolActionIds.back(),  mformtools, gridShortcut);
con's avatar
con committed
504 505

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutBreak"));
506
    addToolAction(m_fwm->actionBreakLayout(), am, m_contexts,
con's avatar
con committed
507 508 509
                  m_toolActionIds.back(), mformtools);

    m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutAdjustSize"));
510
    const QString adjustShortcut = osMac ? tr("Meta+J") : tr("Ctrl+J");
511
    addToolAction(m_fwm->actionAdjustSize(), am, m_contexts,
512
                  m_toolActionIds.back(),  mformtools, adjustShortcut);
con's avatar
con committed
513 514

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

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

520
    addToolAction(m_fwm->actionLower(), am, m_contexts,
con's avatar
con committed
521 522
                  QLatin1String("FormEditor.Lower"), mformtools);

523
    addToolAction(m_fwm->actionRaise(), am, m_contexts,
con's avatar
con committed
524 525 526
                  QLatin1String("FormEditor.Raise"), mformtools);

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

    m_actionPreview = m_fwm->actionDefaultPreview();
hjk's avatar
hjk committed
530
    QTC_ASSERT(m_actionPreview, return);
531
    addToolAction(m_actionPreview,  am,  m_contexts,
con's avatar
con committed
532 533 534 535 536 537 538
                   QLatin1String("FormEditor.Preview"), mformtools, tr("Ctrl+Alt+R"));

    // Preview in style...
    m_actionGroupPreviewInStyle = m_fwm->actionGroupPreviewInStyle();
    mformtools->addMenu(createPreviewStyleMenu(am, m_actionGroupPreviewInStyle));

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

541
    createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator3"));
con's avatar
con committed
542
    QAction *actionFormSettings = m_fwm->actionShowFormWindowSettingsDialog();
543
    addToolAction(actionFormSettings, am, m_contexts, QLatin1String("FormEditor.FormSettings"), mformtools);
544

545
    createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator4"));
546
    m_actionAboutPlugins = new QAction(tr("About Qt Designer plugins...."), this);
547
    addToolAction(m_actionAboutPlugins,  am,  m_contexts,
548 549 550 551
                   QLatin1String("FormEditor.AboutPlugins"), mformtools);
    connect(m_actionAboutPlugins,  SIGNAL(triggered()), m_fwm, SLOT(aboutPlugins()));
    m_actionAboutPlugins->setEnabled(false);

con's avatar
con committed
552 553 554 555 556 557
    // FWM
    connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface *)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface *)));
}

QToolBar *FormEditorW::createEditorToolBar() const
{
558
    QToolBar *editorToolBar = new QToolBar;
559
    Core::ActionManager *am = m_core->actionManager();
con's avatar
con committed
560 561
    const QStringList::const_iterator cend = m_toolActionIds.constEnd();
    for (QStringList::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
con's avatar
con committed
562
        Core::Command *cmd = am->command(*it);
hjk's avatar
hjk committed
563
        QTC_ASSERT(cmd, continue);
con's avatar
con committed
564 565
        QAction *action = cmd->action();
        if (!action->icon().isNull()) // Simplify grid has no action yet
566
            editorToolBar->addAction(action);
con's avatar
con committed
567
    }
568 569 570 571
    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
572 573
}

574
Core::ActionContainer *FormEditorW::createPreviewStyleMenu(Core::ActionManager *am,
con's avatar
con committed
575 576 577
                                                            QActionGroup *actionGroup)
{
    const QString menuId = QLatin1String(M_FORMEDITOR_PREVIEW);
578
    Core::ActionContainer *menuPreviewStyle = am->createMenu(menuId);
con's avatar
con committed
579 580 581 582 583 584 585 586 587 588 589
    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
590
    foreach (QAction* a, actions) {
con's avatar
con committed
591 592 593 594 595 596 597 598 599
        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();
600
        Core::Command *command = am->registerAction(a, name, m_contexts);
601
        bindShortcut(command, a);
con's avatar
con committed
602
        if (isDeviceProfile) {
con's avatar
con committed
603 604
            command->setAttribute(Core::Command::CA_UpdateText);
            command->setAttribute(Core::Command::CA_NonConfigureable);
con's avatar
con committed
605 606 607 608 609 610 611 612 613
        }
        menuPreviewStyle->addAction(command);
    }
    return menuPreviewStyle;
}

void FormEditorW::saveSettings(QSettings *s)
{
    s->beginGroup(settingsGroup);
614
    m_editorWidget->saveSettings(s);
615
    s->endGroup();
con's avatar
con committed
616 617 618 619 620 621 622
}

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

623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
// 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,
                                     const QList<int> &context,
                                     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);
649
    command->setAttribute(Core::Command::CA_Hide);
650 651 652 653 654 655 656 657 658 659
    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
660 661 662
Core::Command *FormEditorW::addToolAction(QAction *a, Core::ActionManager *am,
                                          const QList<int> &context, const QString &name,
                                          Core::ActionContainer *c1, const QString &keySequence)
663 664 665 666
{
    Core::Command *command = am->registerAction(a, name, context);
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
667 668
    if (!a->isSeparator())
        bindShortcut(command, a);
669
    c1->addAction(command);
670
    return command;
671 672
}

673
EditorData FormEditorW::createEditor(QWidget *parent)
con's avatar
con committed
674
{
675 676 677 678
    if (Designer::Constants::Internal::debug)
        qDebug() << "FormEditorW::createEditor";
    // Create and associate form and text editor.
    EditorData data;
con's avatar
con committed
679
    m_fwm->closeAllPreviews();
680 681
    qdesigner_internal::FormWindowBase *form = qobject_cast<qdesigner_internal::FormWindowBase *>(m_fwm->createFormWindow(0));
    QTC_ASSERT(form, return data);
con's avatar
con committed
682
    connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int)));
683
    ResourceHandler *resourceHandler = new ResourceHandler(form);
684
    form->setDesignerGrid(qdesigner_internal::FormWindowBase::defaultDesignerGrid());
con's avatar
con committed
685
    qdesigner_internal::FormWindowBase::setupDefaultAction(form);
686
    data.widgetHost = new SharedTools::WidgetHost( /* parent */ 0, form);
687 688
    DesignerXmlEditor *xmlEditor = new DesignerXmlEditor(form, parent);
    TextEditor::TextEditorSettings::instance()->initializeEditor(xmlEditor);
689 690
    data.formWindowEditor = xmlEditor->designerEditor();
    connect(data.widgetHost, SIGNAL(formWindowSizeChanged(int,int)),
691
            xmlEditor, SIGNAL(changed()));
692
    connect(data.formWindowEditor->file(), SIGNAL(changed()),
693
            resourceHandler, SLOT(updateResources()));
694
    m_editorWidget->add(data);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
695 696 697

    m_toolBar->addEditor(xmlEditor->editableInterface());

698
    return data;
con's avatar
con committed
699 700
}

701 702 703 704 705 706 707 708 709 710 711
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
712 713
void FormEditorW::currentEditorChanged(Core::IEditor *editor)
{
714 715
    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
con's avatar
con committed
716

Lasse Holmstedt's avatar
Lasse Holmstedt committed
717
    if (editor && editor->id() == QLatin1String(Constants::K_DESIGNER_XML_EDITOR_ID)) {
718
        FormWindowEditor *xmlEditor = qobject_cast<FormWindowEditor *>(editor);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
719
        QTC_ASSERT(xmlEditor, return);
720
        ensureInitStage(FullyInitialized);
721
        SharedTools::WidgetHost *fw = m_editorWidget->formWindowEditorForXmlEditor(xmlEditor);
722 723
        QTC_ASSERT(fw, return)
        m_editorWidget->setVisibleEditor(xmlEditor);
con's avatar
con committed
724 725 726 727 728 729
        m_fwm->setActiveFormWindow(fw->formWindow());
    }
}

void FormEditorW::activeFormWindowChanged(QDesignerFormWindowInterface *afw)
{
730
    if (Designer::Constants::Internal::debug)
731
        qDebug() << Q_FUNC_INFO << afw << " of " << m_fwm->formWindowCount();
con's avatar
con committed
732 733

    m_fwm->closeAllPreviews();
734 735
    m_actionPreview->setEnabled(afw != 0);
    m_actionGroupPreviewInStyle->setEnabled(afw != 0);
con's avatar
con committed
736 737
}

738
EditorData FormEditorW::activeEditor() const
con's avatar
con committed
739
{
740
    if (m_editorWidget)
741 742
        return m_editorWidget->activeEditor();
    return EditorData();
con's avatar
con committed
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
}

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
772 773 774
void FormEditorW::closeFormEditorsForXmlEditors(QList<Core::IEditor*> editors)
{
    foreach(Core::IEditor *editor, editors) {
775
        m_editorWidget->removeFormWindowEditor(editor);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
776 777 778
    }
}

con's avatar
con committed
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
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;
        const QPixmap pixmap = m_fwm->createPreviewPixmap(&errorMessage);
        if (pixmap.isNull()) {
Jure Repinc's avatar
Jure Repinc committed
795
            critical(tr("The image could not be created: %1").arg(errorMessage));
con's avatar
con committed
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
            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);

        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);

        // 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
833

834 835
} // namespace Internal
} // namespace Designer