formeditorw.cpp 30.1 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

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

42
#include <coreplugin/editortoolbar.h>
Lasse Holmstedt's avatar
Lasse Holmstedt committed
43
#include <coreplugin/designmode.h>
con's avatar
con committed
44
#include <coreplugin/coreconstants.h>
45
#include <coreplugin/icore.h>
kh1's avatar
kh1 committed
46
#include <coreplugin/helpmanager.h>
47
#include <coreplugin/actionmanager/actionmanager.h>
48
#include <coreplugin/actionmanager/actioncontainer.h>
49
#include <coreplugin/minisplitter.h>
50
#include <coreplugin/mimedatabase.h>
51
#include <coreplugin/outputpane.h>
hjk's avatar
hjk committed
52
#include <utils/qtcassert.h>
con's avatar
con committed
53

54
55
56
#include <QDesignerFormEditorPluginInterface>
#include <QDesignerFormEditorInterface>
#include <QDesignerComponents>
57
#include <QDesignerFormWindowManagerInterface>
58
59
60
61
#include <QDesignerWidgetBoxInterface>
#include <abstractobjectinspector.h>
#include <QDesignerPropertyEditorInterface>
#include <QDesignerActionEditorInterface>
con's avatar
con committed
62

63
64
65
66
67
68
69
70
71
72
73
74
75
#include <QAction>
#include <QActionGroup>
#include <QApplication>
#include <QCursor>
#include <QDockWidget>
#include <QMessageBox>
#include <QKeySequence>
#include <QPrintDialog>
#include <QPrinter>
#include <QPainter>
#include <QStyle>
#include <QToolBar>
#include <QVBoxLayout>
con's avatar
con committed
76

77
78
79
80
81
#include <QDebug>
#include <QSettings>
#include <QSignalMapper>
#include <QPluginLoader>
#include <QTime>
con's avatar
con committed
82

83
static const char settingsGroupC[] = "Designer";
con's avatar
con committed
84

85
86
/* Actions of the designer plugin:
 * Designer provides a toolbar which is subject to a context change (to
Tobias Hunger's avatar
Tobias Hunger committed
87
 * "edit mode" context) when it is focused.
88
89
90
91
92
 * 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
93
94
static inline QIcon designerIcon(const QString &iconName)
{
95
    const QIcon icon = QDesignerFormEditorInterface::createIcon(iconName);
con's avatar
con committed
96
97
98
99
100
    if (icon.isNull())
        qWarning() << "Unable to locate " << iconName;
    return icon;
}

hjk's avatar
hjk committed
101
using namespace Core;
con's avatar
con committed
102
103
using namespace Designer::Constants;

104
105
namespace Designer {
namespace Internal {
con's avatar
con committed
106
107
108

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

con's avatar
con committed
109
110
111
112
113
114
115
116
FormEditorW *FormEditorW::m_self = 0;

FormEditorW::FormEditorW() :
    m_formeditor(QDesignerComponents::createFormEditor(0)),
    m_integration(0),
    m_fwm(0),
    m_initStage(RegisterPlugins),
    m_actionGroupEditMode(0),
117
118
119
    m_actionPrint(0),
    m_actionPreview(0),
    m_actionGroupPreviewInStyle(0),
120
    m_previewInStyleMenu(0),
121
    m_actionAboutPlugins(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
122
123
    m_shortcutMapper(new QSignalMapper(this)),
    m_context(0),
124
125
    m_modeWidget(0),
    m_editorWidget(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
126
127
128
    m_designMode(0),
    m_editorToolBar(0),
    m_toolBar(0)
con's avatar
con committed
129
{
130
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
131
        qDebug() << Q_FUNC_INFO;
hjk's avatar
hjk committed
132
    QTC_ASSERT(!m_self, return);
con's avatar
con committed
133
134
135
136
137
    m_self = this;

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

hjk's avatar
hjk committed
138
    m_formeditor->setTopLevel(ICore::mainWindow());
con's avatar
con committed
139
140
    m_formeditor->setSettingsManager(new SettingsManager());

141
    m_fwm = m_formeditor->formWindowManager();
hjk's avatar
hjk committed
142
    QTC_ASSERT(m_fwm, return);
con's avatar
con committed
143

144
    m_contexts.add(Designer::Constants::C_FORMEDITOR);
145

con's avatar
con committed
146
147
148
149
150
151
152
    setupActions();

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

hjk's avatar
hjk committed
153
    connect(EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
Robert Loehning's avatar
Robert Loehning committed
154
155
156
            this, SLOT(currentEditorChanged(Core::IEditor*)));
    connect(m_shortcutMapper, SIGNAL(mapped(QObject*)),
            this, SLOT(updateShortcut(QObject*)));
con's avatar
con committed
157
158
159
160
}

FormEditorW::~FormEditorW()
{
161
    if (m_context)
hjk's avatar
hjk committed
162
        ICore::removeContextObject(m_context);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
163
    if (m_initStage == FullyInitialized) {
hjk's avatar
hjk committed
164
        QSettings *s = ICore::settings();
165
166
167
        s->beginGroup(QLatin1String(settingsGroupC));
        m_editorWidget->saveSettings(s);
        s->endGroup();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
168

169
170
171
172
        m_designMode->unregisterDesignWidget(m_modeWidget);
        delete m_modeWidget;
        m_modeWidget = 0;
    }
con's avatar
con committed
173
174

    delete m_formeditor;
175
176
    qDeleteAll(m_settingsPages);
    m_settingsPages.clear();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
177
178
    delete m_integration;

179
180
181
    m_self = 0;
}

182
// Add an actioon to toggle the view state of a dock window
hjk's avatar
hjk committed
183
184
void FormEditorW::addDockViewAction(ActionContainer *viewMenu,
                                    int index, const Context &context,
185
                                    const QString &title, Id id)
186
187
188
189
{
    if (const QDockWidget *dw = m_editorWidget->designerDockWidgets()[index]) {
        QAction *action = dw->toggleViewAction();
        action->setText(title);
hjk's avatar
hjk committed
190
191
        Command *cmd = addToolAction(action, context, id, viewMenu, QString());
        cmd->setAttribute(Command::CA_Hide);
192
193
194
195
196
197
    }
}

void FormEditorW::setupViewActions()
{
    // Populate "View" menu of form editor menu
hjk's avatar
hjk committed
198
    ActionContainer *viewMenu = ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS);
199
    QTC_ASSERT(viewMenu, return);
200

Eike Ziller's avatar
Eike Ziller committed
201
    addDockViewAction(viewMenu, WidgetBoxSubWindow, m_contexts,
hjk's avatar
hjk committed
202
                      tr("Widget box"), "FormEditor.WidgetBox");
Lasse Holmstedt's avatar
Lasse Holmstedt committed
203

Eike Ziller's avatar
Eike Ziller committed
204
    addDockViewAction(viewMenu, ObjectInspectorSubWindow, m_contexts,
hjk's avatar
hjk committed
205
                      tr("Object Inspector"), "FormEditor.ObjectInspector");
Lasse Holmstedt's avatar
Lasse Holmstedt committed
206

Eike Ziller's avatar
Eike Ziller committed
207
    addDockViewAction(viewMenu, PropertyEditorSubWindow, m_contexts,
hjk's avatar
hjk committed
208
                      tr("Property Editor"), "FormEditor.PropertyEditor");
209

Eike Ziller's avatar
Eike Ziller committed
210
    addDockViewAction(viewMenu, SignalSlotEditorSubWindow, m_contexts,
hjk's avatar
hjk committed
211
                      tr("Signals && Slots Editor"), "FormEditor.SignalsAndSlotsEditor");
212

Eike Ziller's avatar
Eike Ziller committed
213
    addDockViewAction(viewMenu, ActionEditorSubWindow, m_contexts,
hjk's avatar
hjk committed
214
                      tr("Action Editor"), "FormEditor.ActionEditor");
215
216
    // Reset
    Command *cmd = addToolAction(m_editorWidget->menuSeparator(), m_contexts, "FormEditor.SeparatorReset", viewMenu);
hjk's avatar
hjk committed
217
    cmd->setAttribute(Command::CA_Hide);
218

hjk's avatar
hjk committed
219
    cmd = addToolAction(m_editorWidget->resetLayoutAction(), m_contexts, "FormEditor.ResetToDefaultLayout", viewMenu);
220
    connect(m_editorWidget, SIGNAL(resetLayout()), m_editorWidget, SLOT(resetToDefaultLayout()));
hjk's avatar
hjk committed
221
    cmd->setAttribute(Command::CA_Hide);
con's avatar
con committed
222
223
224
225
}

void FormEditorW::fullInit()
{
hjk's avatar
hjk committed
226
    QTC_ASSERT(m_initStage == RegisterPlugins, return);
con's avatar
con committed
227
    QTime *initTime = 0;
228
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
229
230
231
232
233
234
235
236
        initTime = new QTime;
        initTime->start();
    }

    QDesignerComponents::createTaskMenu(m_formeditor, parent());
    QDesignerComponents::initializePlugins(designerEditor());
    QDesignerComponents::initializeResources();
    initDesignerSubWindows();
237
    m_integration = new QtCreatorIntegration(m_formeditor, this);
con's avatar
con committed
238
    m_formeditor->setIntegration(m_integration);
239
    // Connect Qt Designer help request to HelpManager.
kh1's avatar
kh1 committed
240
    connect(m_integration, SIGNAL(creatorHelpRequested(QUrl)),
241
        HelpManager::instance(), SLOT(handleHelpRequest(QUrl)));
con's avatar
con committed
242
243
244
245
246

    /**
     * This will initialize our TabOrder, Signals and slots and Buddy editors.
     */
    QList<QObject*> plugins = QPluginLoader::staticInstances();
247
    plugins += m_formeditor->pluginInstances();
con's avatar
con committed
248
249
250
251
252
253
254
    foreach (QObject *plugin, plugins) {
        if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
            if (!formEditorPlugin->isInitialized())
                formEditorPlugin->initialize(m_formeditor);
        }
    }

255
256
257
    if (m_actionAboutPlugins)
        m_actionAboutPlugins->setEnabled(true);

258
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
259
260
261
        qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
        delete initTime;
    }
262

hjk's avatar
hjk committed
263
    connect(EditorManager::instance(), SIGNAL(editorsClosed(QList<Core::IEditor*>)),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
264
            SLOT(closeFormEditorsForXmlEditors(QList<Core::IEditor*>)));
265
266
    // Nest toolbar and editor widget
    m_editorWidget = new EditorWidget(this);
hjk's avatar
hjk committed
267
    QSettings *settings = ICore::settings();
268
    settings->beginGroup(QLatin1String(settingsGroupC));
269
270
    m_editorWidget->restoreSettings(settings);
    settings->endGroup();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
271

Lasse Holmstedt's avatar
Lasse Holmstedt committed
272
    m_editorToolBar = createEditorToolBar();
273
    m_toolBar = new EditorToolBar;
hjk's avatar
hjk committed
274
    m_toolBar->setToolbarCreationFlags(EditorToolBar::FlagsStandalone);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
275
276
277
    m_toolBar->setNavigationVisible(false);
    m_toolBar->addCenterToolBar(m_editorToolBar);

hjk's avatar
hjk committed
278
    m_designMode = DesignMode::instance();
279
280
281
282
283
    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
284
    layout->addWidget(m_toolBar);
285
286
    // Avoid mode switch to 'Edit' mode when the application started by
    // 'Run' in 'Design' mode emits output.
hjk's avatar
hjk committed
287
    MiniSplitter *splitter = new MiniSplitter(Qt::Vertical);
288
    splitter->addWidget(m_editorWidget);
hjk's avatar
hjk committed
289
    QWidget *outputPane = new OutputPanePlaceHolder(m_designMode, splitter);
290
291
    outputPane->setObjectName(QLatin1String("DesignerOutputPanePlaceHolder"));
    splitter->addWidget(outputPane);
292
    layout->addWidget(splitter);
293
294
    m_modeWidget->setLayout(layout);

hjk's avatar
hjk committed
295
    Context designerContexts = m_contexts;
296
    designerContexts.add(Core::Constants::C_EDITORMANAGER);
297
    m_context = new DesignerContext(designerContexts, m_modeWidget, this);
hjk's avatar
hjk committed
298
    ICore::addContextObject(m_context);
299

300
    m_designMode->registerDesignWidget(m_modeWidget, QStringList(QLatin1String(FORM_MIMETYPE)), m_contexts);
301
302

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

con's avatar
con committed
304
305
306
307
308
309
310
311
    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
312
    wb->setWindowTitle(tr("Widget Box"));
313
    wb->setObjectName(QLatin1String("WidgetBox"));
con's avatar
con committed
314
315
316
317
    m_formeditor->setWidgetBox(wb);
    m_designerSubWindows[WidgetBoxSubWindow] = wb;

    QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, 0);
con's avatar
con committed
318
    oi->setWindowTitle(tr("Object Inspector"));
319
    oi->setObjectName(QLatin1String("ObjectInspector"));
con's avatar
con committed
320
321
322
323
    m_formeditor->setObjectInspector(oi);
    m_designerSubWindows[ObjectInspectorSubWindow] = oi;

    QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, 0);
con's avatar
con committed
324
    pe->setWindowTitle(tr("Property Editor"));
325
    pe->setObjectName(QLatin1String("PropertyEditor"));
con's avatar
con committed
326
327
328
329
    m_formeditor->setPropertyEditor(pe);
    m_designerSubWindows[PropertyEditorSubWindow] = pe;

    QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, 0);
Daniel Molkentin's avatar
Daniel Molkentin committed
330
    se->setWindowTitle(tr("Signals && Slots Editor"));
331
    se->setObjectName(QLatin1String("SignalsAndSlotsEditor"));
con's avatar
con committed
332
333
334
    m_designerSubWindows[SignalSlotEditorSubWindow] = se;

    QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, 0);
con's avatar
con committed
335
    ae->setWindowTitle(tr("Action Editor"));
336
    ae->setObjectName(QLatin1String("ActionEditor"));
con's avatar
con committed
337
338
339
340
    m_formeditor->setActionEditor(ae);
    m_designerSubWindows[ActionEditorSubWindow] = ae;
}

341
342
343
344
345
QList<Core::IOptionsPage *> FormEditorW::optionsPages() const
{
    return m_settingsPages;
}

con's avatar
con committed
346
347
void FormEditorW::ensureInitStage(InitializationStage s)
{
348
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
        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()
{
    //menus
hjk's avatar
hjk committed
373
    ActionContainer *medit = ActionManager::actionContainer(Core::Constants::M_EDIT);
374
    ActionContainer *mformtools = ActionManager::actionContainer(M_FORMEDITOR);
con's avatar
con committed
375
376

    //overridden actions
hjk's avatar
hjk committed
377
378
379
380
381
382
    bindShortcut(ActionManager::registerAction(m_fwm->actionUndo(), Core::Constants::UNDO, m_contexts), m_fwm->actionUndo());
    bindShortcut(ActionManager::registerAction(m_fwm->actionRedo(), Core::Constants::REDO, m_contexts), m_fwm->actionRedo());
    bindShortcut(ActionManager::registerAction(m_fwm->actionCut(), Core::Constants::CUT, m_contexts), m_fwm->actionCut());
    bindShortcut(ActionManager::registerAction(m_fwm->actionCopy(), Core::Constants::COPY, m_contexts), m_fwm->actionCopy());
    bindShortcut(ActionManager::registerAction(m_fwm->actionPaste(), Core::Constants::PASTE, m_contexts), m_fwm->actionPaste());
    bindShortcut(ActionManager::registerAction(m_fwm->actionSelectAll(), Core::Constants::SELECTALL, m_contexts), m_fwm->actionSelectAll());
con's avatar
con committed
383
384

    m_actionPrint = new QAction(this);
hjk's avatar
hjk committed
385
    bindShortcut(ActionManager::registerAction(m_actionPrint, Core::Constants::PRINT, m_contexts), m_actionPrint);
con's avatar
con committed
386
387
    connect(m_actionPrint, SIGNAL(triggered()), this, SLOT(print()));

388
389
390
    //'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
391
    Command *command;
392
    command = ActionManager::registerAction(m_fwm->actionDelete(), "FormEditor.Edit.Delete", m_contexts);
393
    bindShortcut(command, m_fwm->actionDelete());
hjk's avatar
hjk committed
394
    command->setAttribute(Command::CA_Hide);
con's avatar
con committed
395
396
397
398
399
400
    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*)));

401
    medit->addSeparator(m_contexts, Core::Constants::G_EDIT_OTHER);
con's avatar
con committed
402

403
    m_toolActionIds.push_back("FormEditor.WidgetEditor");
Eike Ziller's avatar
Eike Ziller committed
404
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
405
                         tr("Edit Widgets"), m_toolActionIds.back(),
con's avatar
con committed
406
407
                         EditModeWidgetEditor, QLatin1String("widgettool.png"), tr("F3"));

408
    m_toolActionIds.push_back("FormEditor.SignalsSlotsEditor");
Eike Ziller's avatar
Eike Ziller committed
409
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
410
                         tr("Edit Signals/Slots"), m_toolActionIds.back(),
con's avatar
con committed
411
412
                         EditModeSignalsSlotEditor, QLatin1String("signalslottool.png"), tr("F4"));

413
    m_toolActionIds.push_back("FormEditor.BuddyEditor");
Eike Ziller's avatar
Eike Ziller committed
414
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
415
                         tr("Edit Buddies"), m_toolActionIds.back(),
con's avatar
con committed
416
417
                         EditModeBuddyEditor, QLatin1String("buddytool.png"));

418
    m_toolActionIds.push_back("FormEditor.TabOrderEditor");
Eike Ziller's avatar
Eike Ziller committed
419
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
420
                         tr("Edit Tab Order"),  m_toolActionIds.back(),
con's avatar
con committed
421
422
423
                         EditModeTabOrderEditor, QLatin1String("tabordertool.png"));

    //tool actions
424
    m_toolActionIds.push_back("FormEditor.LayoutHorizontally");
hjk's avatar
hjk committed
425
    const QString horizLayoutShortcut = UseMacShortcuts ? tr("Meta+Shift+H") : tr("Ctrl+H");
Eike Ziller's avatar
Eike Ziller committed
426
    addToolAction(m_fwm->actionHorizontalLayout(), m_contexts,
427
428
                  m_toolActionIds.back(), mformtools, horizLayoutShortcut);

429
    m_toolActionIds.push_back("FormEditor.LayoutVertically");
hjk's avatar
hjk committed
430
    const QString vertLayoutShortcut = UseMacShortcuts ? tr("Meta+L") : tr("Ctrl+L");
Eike Ziller's avatar
Eike Ziller committed
431
    addToolAction(m_fwm->actionVerticalLayout(), m_contexts,
432
                  m_toolActionIds.back(),  mformtools, vertLayoutShortcut);
con's avatar
con committed
433

434
    m_toolActionIds.push_back("FormEditor.SplitHorizontal");
Eike Ziller's avatar
Eike Ziller committed
435
    addToolAction(m_fwm->actionSplitHorizontal(), m_contexts,
con's avatar
con committed
436
437
                  m_toolActionIds.back(), mformtools);

438
    m_toolActionIds.push_back("FormEditor.SplitVertical");
Eike Ziller's avatar
Eike Ziller committed
439
    addToolAction(m_fwm->actionSplitVertical(), m_contexts,
con's avatar
con committed
440
441
                  m_toolActionIds.back(), mformtools);

442
    m_toolActionIds.push_back("FormEditor.LayoutForm");
Eike Ziller's avatar
Eike Ziller committed
443
    addToolAction(m_fwm->actionFormLayout(), m_contexts,
con's avatar
con committed
444
445
                  m_toolActionIds.back(),  mformtools);

446
    m_toolActionIds.push_back("FormEditor.LayoutGrid");
hjk's avatar
hjk committed
447
    const QString gridShortcut = UseMacShortcuts ? tr("Meta+Shift+G") : tr("Ctrl+G");
Eike Ziller's avatar
Eike Ziller committed
448
    addToolAction(m_fwm->actionGridLayout(), m_contexts,
449
                  m_toolActionIds.back(),  mformtools, gridShortcut);
con's avatar
con committed
450

451
    m_toolActionIds.push_back("FormEditor.LayoutBreak");
Eike Ziller's avatar
Eike Ziller committed
452
    addToolAction(m_fwm->actionBreakLayout(), m_contexts,
con's avatar
con committed
453
454
                  m_toolActionIds.back(), mformtools);

455
    m_toolActionIds.push_back("FormEditor.LayoutAdjustSize");
hjk's avatar
hjk committed
456
    const QString adjustShortcut = UseMacShortcuts ? tr("Meta+J") : tr("Ctrl+J");
Eike Ziller's avatar
Eike Ziller committed
457
    addToolAction(m_fwm->actionAdjustSize(), m_contexts,
458
                  m_toolActionIds.back(),  mformtools, adjustShortcut);
con's avatar
con committed
459

460
    m_toolActionIds.push_back("FormEditor.SimplifyLayout");
Eike Ziller's avatar
Eike Ziller committed
461
    addToolAction(m_fwm->actionSimplifyLayout(), m_contexts,
con's avatar
con committed
462
463
                  m_toolActionIds.back(),  mformtools);

464
    mformtools->addSeparator(m_contexts);
con's avatar
con committed
465

466
467
    addToolAction(m_fwm->actionLower(), m_contexts, "FormEditor.Lower", mformtools);
    addToolAction(m_fwm->actionRaise(), m_contexts, "FormEditor.Raise", mformtools);
con's avatar
con committed
468
469

    // Commands that do not go into the editor toolbar
470
    mformtools->addSeparator(m_contexts);
con's avatar
con committed
471

472
    m_actionPreview = m_fwm->action(QDesignerFormWindowManagerInterface::DefaultPreviewAction);
hjk's avatar
hjk committed
473
    QTC_ASSERT(m_actionPreview, return);
474
    addToolAction(m_actionPreview, m_contexts, "FormEditor.Preview", mformtools, tr("Alt+Shift+R"));
con's avatar
con committed
475
476

    // Preview in style...
477
478
    m_actionGroupPreviewInStyle = m_fwm->actionGroup(QDesignerFormWindowManagerInterface::StyledPreviewActionGroup);

hjk's avatar
hjk committed
479
    ActionContainer *previewAC = createPreviewStyleMenu(m_actionGroupPreviewInStyle);
480
481
482
    m_previewInStyleMenu = previewAC->menu();
    mformtools->addMenu(previewAC);
    setPreviewMenuEnabled(false);
con's avatar
con committed
483
484

    // Form settings
485
    medit->addSeparator(m_contexts, Core::Constants::G_EDIT_OTHER);
con's avatar
con committed
486

487
    mformtools->addSeparator(m_contexts);
488

489
    mformtools->addSeparator(m_contexts, Core::Constants::G_DEFAULT_THREE);
490
    QAction *actionFormSettings = m_fwm->action(QDesignerFormWindowManagerInterface::FormWindowSettingsDialogAction);
491
492
    addToolAction(actionFormSettings, m_contexts, "FormEditor.FormSettings", mformtools,
                  QString(), Core::Constants::G_DEFAULT_THREE);
493

494
    mformtools->addSeparator(m_contexts, Core::Constants::G_DEFAULT_THREE);
495
    m_actionAboutPlugins = new QAction(tr("About Qt Designer Plugins..."), this);
496
    m_actionAboutPlugins->setMenuRole(QAction::NoRole);
497
498
    addToolAction(m_actionAboutPlugins, m_contexts, "FormEditor.AboutPlugins", mformtools,
                  QString(), Core::Constants::G_DEFAULT_THREE);
499
    connect(m_actionAboutPlugins,  SIGNAL(triggered()), m_fwm, SLOT(showPluginDialog()));
500
501
    m_actionAboutPlugins->setEnabled(false);

con's avatar
con committed
502
    // FWM
Robert Loehning's avatar
Robert Loehning committed
503
    connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
con's avatar
con committed
504
505
506
507
}

QToolBar *FormEditorW::createEditorToolBar() const
{
508
    QToolBar *editorToolBar = new QToolBar;
hjk's avatar
hjk committed
509
510
511
    const QList<Id>::const_iterator cend = m_toolActionIds.constEnd();
    for (QList<Id>::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
        Command *cmd = ActionManager::command(*it);
hjk's avatar
hjk committed
512
        QTC_ASSERT(cmd, continue);
con's avatar
con committed
513
514
        QAction *action = cmd->action();
        if (!action->icon().isNull()) // Simplify grid has no action yet
515
            editorToolBar->addAction(action);
con's avatar
con committed
516
    }
517
518
519
520
    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
521
522
}

hjk's avatar
hjk committed
523
ActionContainer *FormEditorW::createPreviewStyleMenu(QActionGroup *actionGroup)
con's avatar
con committed
524
525
{
    const QString menuId = QLatin1String(M_FORMEDITOR_PREVIEW);
hjk's avatar
hjk committed
526
    ActionContainer *menuPreviewStyle = ActionManager::createMenu(M_FORMEDITOR_PREVIEW);
con's avatar
con committed
527
528
529
530
531
532
533
534
535
536
537
    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
538
    foreach (QAction* a, actions) {
con's avatar
con committed
539
540
541
542
543
544
545
546
547
        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();
hjk's avatar
hjk committed
548
        Command *command = ActionManager::registerAction(a, Id::fromString(name), m_contexts);
549
        bindShortcut(command, a);
con's avatar
con committed
550
        if (isDeviceProfile) {
hjk's avatar
hjk committed
551
552
            command->setAttribute(Command::CA_UpdateText);
            command->setAttribute(Command::CA_NonConfigurable);
con's avatar
con committed
553
554
555
556
557
558
        }
        menuPreviewStyle->addAction(command);
    }
    return menuPreviewStyle;
}

559
560
561
562
563
564
void FormEditorW::setPreviewMenuEnabled(bool e)
{
    m_actionPreview->setEnabled(e);
    m_previewInStyleMenu->setEnabled(e);
}

con's avatar
con committed
565
566
void FormEditorW::saveSettings(QSettings *s)
{
567
    s->beginGroup(QLatin1String(settingsGroupC));
568
    m_editorWidget->saveSettings(s);
569
    s->endGroup();
con's avatar
con committed
570
571
572
573
}

void FormEditorW::critical(const QString &errorMessage)
{
hjk's avatar
hjk committed
574
    QMessageBox::critical(ICore::mainWindow(), tr("Designer"),  errorMessage);
con's avatar
con committed
575
576
}

577
// Apply the command shortcut to the action and connects to the command's keySequenceChanged signal
hjk's avatar
hjk committed
578
void FormEditorW::bindShortcut(Command *command, QAction *action)
579
580
581
582
583
584
585
586
587
588
{
    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,
hjk's avatar
hjk committed
589
590
                                     const Context &context,
                                     ActionContainer *medit,
591
                                     const QString &actionName,
592
                                     Id id,
593
594
595
596
597
598
599
600
                                     int toolNumber,
                                     const QString &iconName,
                                     const QString &keySequence)
{
    QAction *rc = new QAction(actionName, ag);
    rc->setCheckable(true);
    if (!iconName.isEmpty())
         rc->setIcon(designerIcon(iconName));
hjk's avatar
hjk committed
601
    Command *command = ActionManager::registerAction(rc, id, context);
602
    command->setAttribute(Core::Command::CA_Hide);
603
604
605
606
607
608
609
610
611
612
    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
613
Command *FormEditorW::addToolAction(QAction *a, const Context &context, Id id,
614
615
                                          ActionContainer *c1, const QString &keySequence,
                                    Core::Id groupId)
616
{
hjk's avatar
hjk committed
617
    Command *command = ActionManager::registerAction(a, id, context);
618
619
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
620
621
    if (!a->isSeparator())
        bindShortcut(command, a);
622
    c1->addAction(command, groupId);
623
    return command;
624
625
}

626
EditorData FormEditorW::createEditor()
con's avatar
con committed
627
{
628
629
630
631
    if (Designer::Constants::Internal::debug)
        qDebug() << "FormEditorW::createEditor";
    // Create and associate form and text editor.
    EditorData data;
con's avatar
con committed
632
    m_fwm->closeAllPreviews();
633
    QDesignerFormWindowInterface *form = m_fwm->createFormWindow(0);
634
    QTC_ASSERT(form, return data);
con's avatar
con committed
635
    connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int)));
636
    ResourceHandler *resourceHandler = new ResourceHandler(form);
637
    data.widgetHost = new SharedTools::WidgetHost( /* parent */ 0, form);
638
    DesignerXmlEditorWidget *xmlEditor = new DesignerXmlEditorWidget(form);
639
    data.formWindowEditor = xmlEditor->designerEditor();
640
    connect(data.formWindowEditor->document(), SIGNAL(filePathChanged(QString,QString)),
641
            resourceHandler, SLOT(updateResources()));
642
    m_editorWidget->add(data);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
643

644
    m_toolBar->addEditor(xmlEditor->designerEditor());
Lasse Holmstedt's avatar
Lasse Holmstedt committed
645

646
    return data;
con's avatar
con committed
647
648
}

649
650
void FormEditorW::updateShortcut(QObject *command)
{
hjk's avatar
hjk committed
651
    Command *c = qobject_cast<Command *>(command);
652
653
654
655
656
657
658
659
    if (!c)
        return;
    QAction *a = m_commandToDesignerAction.value(c);
    if (!a)
        return;
    a->setShortcut(c->action()->shortcut());
}

hjk's avatar
hjk committed
660
void FormEditorW::currentEditorChanged(IEditor *editor)
con's avatar
con committed
661
{
662
663
    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
con's avatar
con committed
664

665
    if (editor && editor->document()->id() == Constants::K_DESIGNER_XML_EDITOR_ID) {
666
        FormWindowEditor *xmlEditor = qobject_cast<FormWindowEditor *>(editor);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
667
        QTC_ASSERT(xmlEditor, return);
668
        ensureInitStage(FullyInitialized);
669
        SharedTools::WidgetHost *fw = m_editorWidget->formWindowEditorForXmlEditor(xmlEditor);
670
        QTC_ASSERT(fw, return);
671
        m_editorWidget->setVisibleEditor(xmlEditor);
con's avatar
con committed
672
673
674
675
676
677
        m_fwm->setActiveFormWindow(fw->formWindow());
    }
}

void FormEditorW::activeFormWindowChanged(QDesignerFormWindowInterface *afw)
{
678
    if (Designer::Constants::Internal::debug)
679
        qDebug() << Q_FUNC_INFO << afw << " of " << m_fwm->formWindowCount();
con's avatar
con committed
680
681

    m_fwm->closeAllPreviews();
682
    setPreviewMenuEnabled(afw != 0);
con's avatar
con committed
683
684
}

685
EditorData FormEditorW::activeEditor() const
con's avatar
con committed
686
{
687
    if (m_editorWidget)
688
689
        return m_editorWidget->activeEditor();
    return EditorData();
con's avatar
con committed
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
}

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

hjk's avatar
hjk committed
719
void FormEditorW::closeFormEditorsForXmlEditors(QList<IEditor*> editors)
Lasse Holmstedt's avatar
Lasse Holmstedt committed
720
{
hjk's avatar
hjk committed
721
    foreach (IEditor *editor, editors)
722
        m_editorWidget->removeFormWindowEditor(editor);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
723
724
}

con's avatar
con committed
725
726
727
728
729
730
731
void FormEditorW::print()
{
    // Printing code courtesy of designer_actions.cpp
    QDesignerFormWindowInterface *fw = m_fwm->activeFormWindow();
    if (!fw)
        return;

hjk's avatar
hjk committed
732
    QPrinter *printer = ICore::printer();
hjk's avatar
hjk committed
733
734
735
    const bool oldFullPage =  printer->fullPage();
    const QPrinter::Orientation oldOrientation =  printer->orientation ();
    printer->setFullPage(false);
con's avatar
con committed
736
737
738
    do {
        // Grab the image to be able to a suggest suitable orientation
        QString errorMessage;
739
        const QPixmap pixmap = m_fwm->createPreviewPixmap();
con's avatar
con committed
740
        if (pixmap.isNull()) {
Jure Repinc's avatar
Jure Repinc committed
741
            critical(tr("The image could not be created: %1").arg(errorMessage));
con's avatar
con committed
742
743
744
745
            break;
        }

        const QSizeF pixmapSize = pixmap.size();
hjk's avatar
hjk committed
746
        printer->setOrientation( pixmapSize.width() > pixmapSize.height() ?  QPrinter::Landscape :  QPrinter::Portrait);
con's avatar
con committed
747
748

        // Printer parameters
hjk's avatar
hjk committed
749
        QPrintDialog dialog(printer, fw);
con's avatar
con committed
750
751
752
        if (!dialog.exec())
           break;

hjk's avatar
hjk committed
753
        QWidget *mainWindow = ICore::mainWindow();
hjk's avatar
hjk committed
754
755
        const QCursor oldCursor = mainWindow->cursor();
        mainWindow->setCursor(Qt::WaitCursor);
con's avatar
con committed
756
        // Estimate of required scaling to make form look the same on screen and printer.
hjk's avatar
hjk committed
757
        const double suggestedScaling = static_cast<double>(printer->physicalDpiX()) /  static_cast<double>(fw->physicalDpiX());
con's avatar
con committed
758

hjk's avatar
hjk committed
759
        QPainter painter(printer);
con's avatar
con committed
760
761
762
763
764
765
766
        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
767
768
        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
769
770
771
772
773

        // Draw.
        painter.translate(xOffset, yOffset);
        painter.scale(scaling, scaling);
        painter.drawPixmap(0, 0, pixmap);
hjk's avatar
hjk committed
774
        mainWindow->setCursor(oldCursor);
con's avatar
con committed
775
776

    } while (false);
hjk's avatar
hjk committed
777
778
    printer->setFullPage(oldFullPage);
    printer->setOrientation(oldOrientation);
con's avatar
con committed
779
}
Lasse Holmstedt's avatar
Lasse Holmstedt committed
780

781
782
} // namespace Internal
} // namespace Designer