OSDN Git Service

Rename namespace Core::Utils into Utils
[qt-creator-jp/qt-creator-jp.git] / src / plugins / designer / formeditorw.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** Commercial Usage
10 **
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** 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
26 ** contact the sales department at http://qt.nokia.com/contact.
27 **
28 **************************************************************************/
29
30 #include "formeditorw.h"
31 #include "formwindoweditor.h"
32 #include "designerconstants.h"
33 #include "settingsmanager.h"
34 #include "settingspage.h"
35 #include "editorwidget.h"
36 #include "qtcreatorintegration.h"
37
38 #include <coreplugin/coreconstants.h>
39 #include <coreplugin/icore.h>
40 #include <coreplugin/uniqueidmanager.h>
41 #include <coreplugin/actionmanager/actionmanager.h>
42 #include <coreplugin/editormanager/editormanager.h>
43 #include <extensionsystem/pluginmanager.h>
44 #include <utils/qtcassert.h>
45
46 #include <QtDesigner/QDesignerFormEditorPluginInterface>
47 #include <qt_private/pluginmanager_p.h>
48
49 #include <qt_private/iconloader_p.h>  // createIconSet
50 #include <qt_private/qdesigner_formwindowmanager_p.h>
51 #include <qt_private/formwindowbase_p.h>
52 #include <QtDesigner/QDesignerFormEditorInterface>
53 #include <QtDesigner/QDesignerComponents>
54
55 #include <QtDesigner/QDesignerWidgetBoxInterface>
56 #include <QtDesigner/abstractobjectinspector.h>
57 #include <QtDesigner/QDesignerComponents>
58 #include <QtDesigner/QDesignerPropertyEditorInterface>
59 #include <QtDesigner/QDesignerActionEditorInterface>
60
61 #include <QtCore/QPluginLoader>
62 #include <QtCore/QTemporaryFile>
63 #include <QtCore/QDir>
64 #include <QtCore/QTime>
65 #include <QtGui/QAction>
66 #include <QtGui/QActionGroup>
67 #include <QtGui/QApplication>
68 #include <QtGui/QCursor>
69 #include <QtGui/QDockWidget>
70 #include <QtGui/QMenu>
71 #include <QtGui/QMainWindow>
72 #include <QtGui/QMessageBox>
73 #include <QtGui/QKeySequence>
74 #include <QtGui/QPrintDialog>
75 #include <QtGui/QPrinter>
76 #include <QtGui/QPainter>
77 #include <QtGui/QStatusBar>
78 #include <QtGui/QStyle>
79 #include <QtGui/QToolBar>
80
81 #include <QtCore/QDebug>
82 #include <QtCore/QSettings>
83
84 static const char *settingsGroup = "Designer";
85
86 #ifdef Q_OS_MAC
87     enum { osMac = 1 };
88 #else
89     enum { osMac = 0 };
90 #endif
91
92 /* Actions of the designer plugin:
93  * Designer provides a toolbar which is subject to a context change (to
94  * "edit mode" context) when it is focussed.
95  * In order to prevent its actions from being disabled/hidden by that context
96  * change, the actions are registered on the global context. In currentEditorChanged(),
97  * the ones that are present in the global edit menu are set visible/invisible manually.
98  * The designer context is currently used for Cut/Copy/Paste, etc. */
99
100 static inline QIcon designerIcon(const QString &iconName)
101 {
102     const QIcon icon = qdesigner_internal::createIconSet(iconName);
103     if (icon.isNull())
104         qWarning() << "Unable to locate " << iconName;
105     return icon;
106 }
107
108 // Create an action to activate a designer tool
109 static inline QAction *createEditModeAction(QActionGroup *ag,
110                                      const QList<int> &context,
111                                      Core::ActionManager *am,
112                                      Core::ActionContainer *medit,
113                                      const QString &actionName,
114                                      const QString &name,
115                                      int toolNumber,
116                                      const QString &iconName =  QString(),
117                                      const QString &keySequence = QString())
118 {
119     QAction *rc = new QAction(actionName, ag);
120     rc->setCheckable(true);
121     if (!iconName.isEmpty())
122          rc->setIcon(designerIcon(iconName));
123     Core::Command *command = am->registerAction(rc, name, context);
124     if (!keySequence.isEmpty())
125         command->setDefaultKeySequence(QKeySequence(keySequence));
126     medit->addAction(command, Core::Constants::G_EDIT_OTHER);
127     rc->setData(toolNumber);
128     ag->addAction(rc);
129     return rc;
130 }
131
132
133 // Create a menu separato
134 static inline QAction * createSeparator(QObject *parent,
135                                  Core::ActionManager *am,
136                                  const QList<int> &context,
137                                  Core::ActionContainer *container,
138                                  const QString &name = QString(),
139                                  const QString &group = QString())
140 {
141     QAction *actSeparator = new QAction(parent);
142     actSeparator->setSeparator(true);
143     Core::Command *command = am->registerAction(actSeparator, name, context);
144     container->addAction(command, group);
145     return actSeparator;
146 }
147
148 // Create a tool action
149 static inline void addToolAction(QAction *a,
150                    Core::ActionManager *am,
151                    const QList<int> &context,
152                    const QString &name,
153                    Core::ActionContainer *c1,
154                    const QString &keySequence = QString())
155 {
156     Core::Command *command = am->registerAction(a, name, context);
157     if (!keySequence.isEmpty())
158         command->setDefaultKeySequence(QKeySequence(keySequence));
159     c1->addAction(command);
160 }
161
162 using namespace Designer;
163 using namespace Designer::Internal;
164 using namespace Designer::Constants;
165
166 // --------- Proxy Action
167
168 ProxyAction::ProxyAction(const QString &defaultText, QObject *parent)
169     : QAction(defaultText, parent),
170     m_defaultText(defaultText),
171     m_action(0)
172 {
173     setEnabled(false);
174 }
175
176 void ProxyAction::setAction(QAction *action)
177 {
178     if (m_action) {
179         disconnect(m_action, SIGNAL(changed()), this, SLOT(update()));
180         disconnect(this, SIGNAL(triggered(bool)), m_action, SIGNAL(triggered(bool)));
181         disconnect(this, SIGNAL(toggled(bool)), m_action, SLOT(setChecked(bool)));
182     }
183     m_action = action;
184     if (!m_action) {
185         setEnabled(false);
186 //        if (hasAttribute(CA_Hide))
187 //            m_action->setVisible(false);
188 //        if (hasAttribute(CA_UpdateText)) {
189             setText(m_defaultText);
190 //        }
191     } else {
192         setCheckable(m_action->isCheckable());
193         setSeparator(m_action->isSeparator());
194         connect(m_action, SIGNAL(changed()), this, SLOT(update()));
195         // we want to avoid the toggling semantic on slot trigger(), so we just connect the signals
196         connect(this, SIGNAL(triggered(bool)), m_action, SIGNAL(triggered(bool)));
197         // we need to update the checked state, so we connect to setChecked slot, which also fires a toggled signal
198         connect(this, SIGNAL(toggled(bool)), m_action, SLOT(setChecked(bool)));
199         update();
200     }
201 }
202
203 void ProxyAction::update()
204 {
205     QTC_ASSERT(m_action, return)
206     bool block = blockSignals(true);
207 //    if (hasAttribute(CA_UpdateIcon)) {
208         setIcon(m_action->icon());
209         setIconText(m_action->iconText());
210 //    }
211 //    if (hasAttribute(CA_UpdateText)) {
212         setText(m_action->text());
213         setToolTip(m_action->toolTip());
214         setStatusTip(m_action->statusTip());
215         setWhatsThis(m_action->whatsThis());
216 //    }
217
218     setChecked(m_action->isChecked());
219
220     setEnabled(m_action->isEnabled());
221     setVisible(m_action->isVisible());
222     blockSignals(block);
223     emit changed();
224 }
225
226 // --------- FormEditorW
227
228 FormEditorW *FormEditorW::m_self = 0;
229
230 FormEditorW::FormEditorW() :
231     m_formeditor(QDesignerComponents::createFormEditor(0)),
232     m_integration(0),
233     m_fwm(0),
234     m_core(Core::ICore::instance()),
235     m_initStage(RegisterPlugins),
236     m_actionGroupEditMode(0),
237     m_actionPrint(0),
238     m_actionPreview(0),
239     m_actionGroupPreviewInStyle(0),
240     m_actionAboutPlugins(0)
241 {
242     if (Designer::Constants::Internal::debug)
243         qDebug() << Q_FUNC_INFO;
244     QTC_ASSERT(!m_self, return);
245     m_self = this;
246     QTC_ASSERT(m_core, return);
247
248     qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount,
249           static_cast<QWidget *>(0));
250     qFill(m_designerSubWindowActions, m_designerSubWindowActions + Designer::Constants::DesignerSubWindowCount,
251           static_cast<ProxyAction *>(0));
252
253     m_formeditor->setTopLevel(qobject_cast<QWidget *>(m_core->editorManager()));
254     m_formeditor->setSettingsManager(new SettingsManager());
255
256     m_fwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager*>(m_formeditor->formWindowManager());
257     QTC_ASSERT(m_fwm, return);
258
259     const int uid = m_core->uniqueIDManager()->uniqueIdentifier(QLatin1String(C_FORMEDITOR));
260     m_context << uid;
261
262     setupActions();
263
264     foreach (QDesignerOptionsPageInterface *designerPage, m_formeditor->optionsPages()) {
265         SettingsPage *settingsPage = new SettingsPage(designerPage);
266         ExtensionSystem::PluginManager::instance()->addObject(settingsPage);
267         m_settingsPages.append(settingsPage);
268     }
269     restoreSettings(m_core->settings());
270
271     connect(m_core->editorManager(), SIGNAL(currentEditorChanged(Core::IEditor *)),
272             this, SLOT(currentEditorChanged(Core::IEditor *)));
273 }
274
275 FormEditorW::~FormEditorW()
276 {
277     saveSettings(m_core->settings());
278
279     for (int i = 0; i < Designer::Constants::DesignerSubWindowCount; ++i)
280         delete m_designerSubWindows[i];
281
282     delete m_formeditor;
283     foreach (SettingsPage *settingsPage, m_settingsPages) {
284         ExtensionSystem::PluginManager::instance()->removeObject(settingsPage);
285         delete settingsPage;
286     }
287     delete  m_integration;
288     m_self = 0;
289 }
290
291 void FormEditorW::fullInit()
292 {
293     QTC_ASSERT(m_initStage == RegisterPlugins, return);
294     QTime *initTime = 0;
295     if (Designer::Constants::Internal::debug) {
296         initTime = new QTime;
297         initTime->start();
298     }
299
300     QDesignerComponents::createTaskMenu(m_formeditor, parent());
301     QDesignerComponents::initializePlugins(designerEditor());
302     QDesignerComponents::initializeResources();
303     initDesignerSubWindows();
304     m_integration = new QtCreatorIntegration(m_formeditor, this);
305     m_formeditor->setIntegration(m_integration);
306
307     /**
308      * This will initialize our TabOrder, Signals and slots and Buddy editors.
309      */
310     QList<QObject*> plugins = QPluginLoader::staticInstances();
311     plugins += m_formeditor->pluginManager()->instances();
312     foreach (QObject *plugin, plugins) {
313         if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
314             if (!formEditorPlugin->isInitialized())
315                 formEditorPlugin->initialize(m_formeditor);
316         }
317     }
318
319     if (m_actionAboutPlugins)
320         m_actionAboutPlugins->setEnabled(true);
321
322     if (Designer::Constants::Internal::debug) {
323         qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
324         delete initTime;
325     }
326
327     m_initStage = FullyInitialized;
328 }
329
330 void FormEditorW::initDesignerSubWindows()
331 {
332     qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount, static_cast<QWidget*>(0));
333
334     QDesignerWidgetBoxInterface *wb = QDesignerComponents::createWidgetBox(m_formeditor, 0);
335     wb->setWindowTitle(tr("Widget Box"));
336     m_formeditor->setWidgetBox(wb);
337     m_designerSubWindows[WidgetBoxSubWindow] = wb;
338
339     QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, 0);
340     oi->setWindowTitle(tr("Object Inspector"));
341     m_formeditor->setObjectInspector(oi);
342     m_designerSubWindows[ObjectInspectorSubWindow] = oi;
343
344     QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, 0);
345     pe->setWindowTitle(tr("Property Editor"));
346     m_formeditor->setPropertyEditor(pe);
347     m_designerSubWindows[PropertyEditorSubWindow] = pe;
348
349     QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, 0);
350     se->setWindowTitle(tr("Signals & Slots Editor"));
351     m_designerSubWindows[SignalSlotEditorSubWindow] = se;
352
353     QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, 0);
354     ae->setWindowTitle(tr("Action Editor"));
355     m_formeditor->setActionEditor(ae);
356     m_designerSubWindows[ActionEditorSubWindow] = ae;
357 }
358
359 void FormEditorW::ensureInitStage(InitializationStage s)
360 {
361     if (Designer::Constants::Internal::debug)
362         qDebug() << Q_FUNC_INFO << s;
363     if (!m_self)
364         m_self = new FormEditorW;
365     if (m_self->m_initStage >= s)
366         return;
367     QApplication::setOverrideCursor(Qt::WaitCursor);
368     m_self->fullInit();
369     QApplication::restoreOverrideCursor();
370 }
371
372 FormEditorW *FormEditorW::instance()
373 {
374     ensureInitStage(FullyInitialized);
375     return m_self;
376 }
377
378 void FormEditorW::deleteInstance()
379 {
380     delete m_self;
381 }
382
383 void FormEditorW::setupActions()
384 {
385     Core::ActionManager *am = m_core->actionManager();
386     Core::Command *command;
387
388     //menus
389     Core::ActionContainer *medit =
390         am->actionContainer(Core::Constants::M_EDIT);
391     Core::ActionContainer *mtools =
392         am->actionContainer(Core::Constants::M_TOOLS);
393
394     Core::ActionContainer *mformtools =
395         am->createMenu(M_FORMEDITOR);
396     mformtools->menu()->setTitle(tr("For&m editor"));
397     mtools->addMenu(mformtools);
398
399     //overridden actions
400     am->registerAction(m_fwm->actionUndo(), Core::Constants::UNDO, m_context);
401     am->registerAction(m_fwm->actionRedo(), Core::Constants::REDO, m_context);
402     am->registerAction(m_fwm->actionCut(), Core::Constants::CUT, m_context);
403     am->registerAction(m_fwm->actionCopy(), Core::Constants::COPY, m_context);
404     am->registerAction(m_fwm->actionPaste(), Core::Constants::PASTE, m_context);
405     am->registerAction(m_fwm->actionSelectAll(), Core::Constants::SELECTALL, m_context);
406
407     m_actionPrint = new QAction(this);
408     am->registerAction(m_actionPrint, Core::Constants::PRINT, m_context);
409     connect(m_actionPrint, SIGNAL(triggered()), this, SLOT(print()));
410
411     //'delete' action
412     command = am->registerAction(m_fwm->actionDelete(), QLatin1String("FormEditor.Edit.Delete"), m_context);
413     command->setDefaultKeySequence(QKeySequence::Delete);
414     command->setAttribute(Core::Command::CA_Hide);
415     medit->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
416
417     QList<int> globalcontext;
418     globalcontext << m_core->uniqueIDManager()->uniqueIdentifier(Core::Constants::C_GLOBAL);
419
420     m_actionGroupEditMode = new QActionGroup(this);
421     m_actionGroupEditMode->setExclusive(true);
422     connect(m_actionGroupEditMode, SIGNAL(triggered(QAction*)), this, SLOT(activateEditMode(QAction*)));
423
424     m_modeActionSeparator = new QAction(this);
425     m_modeActionSeparator->setSeparator(true);
426     command = am->registerAction(m_modeActionSeparator, QLatin1String("FormEditor.Sep.ModeActions"), globalcontext);
427     medit->addAction(command, Core::Constants::G_EDIT_OTHER);
428
429     m_toolActionIds.push_back(QLatin1String("FormEditor.WidgetEditor"));
430     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
431                          tr("Edit widgets"), m_toolActionIds.back(),
432                          EditModeWidgetEditor, QLatin1String("widgettool.png"), tr("F3"));
433
434     m_toolActionIds.push_back(QLatin1String("FormEditor.SignalsSlotsEditor"));
435     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
436                          tr("Edit signals/slots"), m_toolActionIds.back(),
437                          EditModeSignalsSlotEditor, QLatin1String("signalslottool.png"), tr("F4"));
438
439     m_toolActionIds.push_back(QLatin1String("FormEditor.BuddyEditor"));
440     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
441                          tr("Edit buddies"), m_toolActionIds.back(),
442                          EditModeBuddyEditor, QLatin1String("buddytool.png"));
443
444     m_toolActionIds.push_back(QLatin1String("FormEditor.TabOrderEditor"));
445     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
446                          tr("Edit tab order"),  m_toolActionIds.back(),
447                          EditModeTabOrderEditor, QLatin1String("tabordertool.png"));
448
449     //tool actions
450     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutHorizontally"));
451     const QString horizLayoutShortcut = osMac ? tr("Meta+H") : tr("Ctrl+H");
452     addToolAction(m_fwm->actionHorizontalLayout(), am, globalcontext,
453                   m_toolActionIds.back(), mformtools, horizLayoutShortcut);
454
455     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutVertically"));
456     const QString vertLayoutShortcut = osMac ? tr("Meta+L") : tr("Ctrl+L");
457     addToolAction(m_fwm->actionVerticalLayout(), am, globalcontext,
458                   m_toolActionIds.back(),  mformtools, vertLayoutShortcut);
459
460     m_toolActionIds.push_back(QLatin1String("FormEditor.SplitHorizontal"));
461     addToolAction(m_fwm->actionSplitHorizontal(), am, globalcontext,
462                   m_toolActionIds.back(), mformtools);
463
464     m_toolActionIds.push_back(QLatin1String("FormEditor.SplitVertical"));
465     addToolAction(m_fwm->actionSplitVertical(), am, globalcontext,
466                   m_toolActionIds.back(), mformtools);
467
468     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutForm"));
469     addToolAction(m_fwm->actionFormLayout(), am, globalcontext,
470                   m_toolActionIds.back(),  mformtools);
471
472     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutGrid"));
473     const QString gridShortcut = osMac ? tr("Meta+G") : tr("Ctrl+G");
474     addToolAction(m_fwm->actionGridLayout(), am, globalcontext,
475                   m_toolActionIds.back(),  mformtools, gridShortcut);
476
477     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutBreak"));
478     addToolAction(m_fwm->actionBreakLayout(), am, globalcontext,
479                   m_toolActionIds.back(), mformtools);
480
481     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutAdjustSize"));
482     const QString adjustShortcut = osMac ? tr("Meta+J") : tr("Ctrl+J");
483     addToolAction(m_fwm->actionAdjustSize(), am, globalcontext,
484                   m_toolActionIds.back(),  mformtools, adjustShortcut);
485
486     m_toolActionIds.push_back(QLatin1String("FormEditor.SimplifyLayout"));
487     addToolAction(m_fwm->actionSimplifyLayout(), am, globalcontext,
488                   m_toolActionIds.back(),  mformtools);
489
490     createSeparator(this, am, m_context, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator1"));
491
492     addToolAction(m_fwm->actionLower(), am, globalcontext,
493                   QLatin1String("FormEditor.Lower"), mformtools);
494
495     addToolAction(m_fwm->actionRaise(), am, globalcontext,
496                   QLatin1String("FormEditor.Raise"), mformtools);
497
498     // Views
499     createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.SeparatorViews"));
500
501     Core::ActionContainer *mviews = am->createMenu(M_FORMEDITOR_VIEWS);
502     mviews->menu()->setTitle(tr("Views"));
503     mformtools->addMenu(mviews);
504
505     m_designerSubWindowActions[WidgetBoxSubWindow] = new ProxyAction(tr("Widget Box"), this);
506     addToolAction(m_designerSubWindowActions[WidgetBoxSubWindow], am, globalcontext,
507                   QLatin1String("FormEditor.WidgetBox"), mviews, "");
508
509     m_designerSubWindowActions[ObjectInspectorSubWindow] = new ProxyAction(tr("Object Inspector"), this);
510     addToolAction(m_designerSubWindowActions[ObjectInspectorSubWindow], am, globalcontext,
511                   QLatin1String("FormEditor.ObjectInspector"), mviews, "");
512
513         m_designerSubWindowActions[PropertyEditorSubWindow] = new ProxyAction(tr("Property Editor"), this);
514     addToolAction(m_designerSubWindowActions[PropertyEditorSubWindow], am, globalcontext,
515                   QLatin1String("FormEditor.PropertyEditor"), mviews, "");
516
517     m_designerSubWindowActions[SignalSlotEditorSubWindow] = new ProxyAction(tr("Signals && Slots Editor"), this);
518     addToolAction(m_designerSubWindowActions[SignalSlotEditorSubWindow], am, globalcontext,
519                   QLatin1String("FormEditor.SignalsAndSlotsEditor"), mviews, "");
520
521     m_designerSubWindowActions[ActionEditorSubWindow] = new ProxyAction(tr("Action Editor"), this);
522     addToolAction(m_designerSubWindowActions[ActionEditorSubWindow], am, globalcontext,
523                   QLatin1String("FormEditor.ActionEditor"), mviews, "");
524
525     createSeparator(this, am, globalcontext, mviews, QLatin1String("FormEditor.Menu.Tools.Views.SeparatorLock"));
526
527     m_lockAction = new QAction(tr("Locked"), this);
528     m_lockAction->setCheckable(true);
529     addToolAction(m_lockAction, am, globalcontext, QLatin1String("FormEditor.Locked"), mviews, "");
530     connect(m_lockAction, SIGNAL(toggled(bool)), this, SLOT(setFormWindowLayoutLocked(bool)));
531
532     createSeparator(this, am, globalcontext, mviews, QLatin1String("FormEditor.Menu.Tools.Views.SeparatorReset"));
533
534     m_resetLayoutAction = new QAction(tr("Reset to Default Layout"), this);
535     addToolAction(m_resetLayoutAction, am, globalcontext, QLatin1String("FormEditor.ResetToDefaultLayout"), mviews, "");
536     connect(m_resetLayoutAction, SIGNAL(triggered()), this, SLOT(resetToDefaultLayout()));
537
538     // Commands that do not go into the editor toolbar
539     createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator2"));
540
541     m_actionPreview = m_fwm->actionDefaultPreview();
542     QTC_ASSERT(m_actionPreview, return);
543     addToolAction(m_actionPreview,  am,  globalcontext,
544                    QLatin1String("FormEditor.Preview"), mformtools, tr("Ctrl+Alt+R"));
545
546     // Preview in style...
547     m_actionGroupPreviewInStyle = m_fwm->actionGroupPreviewInStyle();
548     mformtools->addMenu(createPreviewStyleMenu(am, m_actionGroupPreviewInStyle));
549
550     // Form settings
551     createSeparator(this, am, m_context,  medit, QLatin1String("FormEditor.Edit.Separator2"), Core::Constants::G_EDIT_OTHER);
552
553     createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator3"));
554     QAction *actionFormSettings = m_fwm->actionShowFormWindowSettingsDialog();
555     addToolAction(actionFormSettings, am, globalcontext, QLatin1String("FormEditor.FormSettings"), mformtools);
556
557 #if QT_VERSION > 0x040500
558     createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator4"));
559     m_actionAboutPlugins = new QAction(tr("About Qt Designer plugins...."), this);
560     addToolAction(m_actionAboutPlugins,  am,  globalcontext,
561                    QLatin1String("FormEditor.AboutPlugins"), mformtools);
562     connect(m_actionAboutPlugins,  SIGNAL(triggered()), m_fwm, SLOT(aboutPlugins()));
563     m_actionAboutPlugins->setEnabled(false);
564 #endif
565
566     // FWM
567     connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface *)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface *)));
568 }
569
570
571 QToolBar *FormEditorW::createEditorToolBar() const
572 {
573     QToolBar *toolBar = new QToolBar;
574     Core::ActionManager *am = m_core->actionManager();
575     const QStringList::const_iterator cend = m_toolActionIds.constEnd();
576     for (QStringList::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
577         Core::Command *cmd = am->command(*it);
578         QTC_ASSERT(cmd, continue);
579         QAction *action = cmd->action();
580         if (!action->icon().isNull()) // Simplify grid has no action yet
581             toolBar->addAction(action);
582     }
583     int size = toolBar->style()->pixelMetric(QStyle::PM_SmallIconSize);
584     toolBar->setIconSize(QSize(size, size));
585     toolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
586     return toolBar;
587 }
588
589 Core::ActionContainer *FormEditorW::createPreviewStyleMenu(Core::ActionManager *am,
590                                                             QActionGroup *actionGroup)
591 {
592     const QString menuId = QLatin1String(M_FORMEDITOR_PREVIEW);
593     Core::ActionContainer *menuPreviewStyle = am->createMenu(menuId);
594     menuPreviewStyle->menu()->setTitle(tr("Preview in"));
595
596     // The preview menu is a list of invisible actions for the embedded design
597     // device profiles (integer data) followed by a separator and the styles
598     // (string data). Make device profiles update their text and hide them
599     // in the configuration dialog.
600     const QList<QAction*> actions = actionGroup->actions();
601
602     const QString deviceProfilePrefix = QLatin1String("DeviceProfile");
603     const QChar dot = QLatin1Char('.');
604
605     foreach (QAction* a, actions) {
606         QString name = menuId;
607         name += dot;
608         const QVariant data = a->data();
609         const bool isDeviceProfile = data.type() == QVariant::Int;
610         if (isDeviceProfile) {
611             name += deviceProfilePrefix;
612             name += dot;
613         }
614         name += data.toString();
615         Core::Command *command = am->registerAction(a, name, m_context);
616         if (isDeviceProfile) {
617             command->setAttribute(Core::Command::CA_UpdateText);
618             command->setAttribute(Core::Command::CA_NonConfigureable);
619         }
620         menuPreviewStyle->addAction(command);
621     }
622     return menuPreviewStyle;
623 }
624
625 void FormEditorW::saveSettings(QSettings *s)
626 {
627     s->beginGroup(settingsGroup);
628     EditorWidget::saveState(s);
629     s->endGroup();
630 }
631
632 void FormEditorW::restoreSettings(QSettings *s)
633 {
634     s->beginGroup(settingsGroup);
635     EditorWidget::restoreState(s);
636     s->endGroup();
637 }
638
639
640 void FormEditorW::critical(const QString &errorMessage)
641 {
642     QMessageBox::critical(m_core->mainWindow(), tr("Designer"),  errorMessage);
643 }
644
645 FormWindowEditor *FormEditorW::createFormWindowEditor(QWidget* parentWidget)
646 {
647     m_fwm->closeAllPreviews();
648     QDesignerFormWindowInterface *form = m_fwm->createFormWindow(0);
649     connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int)));
650     qdesigner_internal::FormWindowBase::setupDefaultAction(form);
651     FormWindowEditor *fww = new FormWindowEditor(m_context, form, parentWidget);
652     // Store a pointer to all form windows so we can unselect
653     // all other formwindows except the active one.
654     m_formWindows.append(fww);
655     connect(fww, SIGNAL(destroyed()), this, SLOT(editorDestroyed()));
656     return fww;
657 }
658
659 void FormEditorW::editorDestroyed()
660 {
661     QObject *source = sender();
662
663     if (Designer::Constants::Internal::debug)
664         qDebug() << Q_FUNC_INFO << source;
665
666     for (EditorList::iterator it = m_formWindows.begin(); it != m_formWindows.end(); ) {
667         if (*it == source) {
668             it = m_formWindows.erase(it);
669             break;
670         } else {
671             ++it;
672         }
673     }
674 }
675
676 void FormEditorW::currentEditorChanged(Core::IEditor *editor)
677 {
678     if (Designer::Constants::Internal::debug)
679         qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
680
681     // Deactivate Designer if a non-form is being edited
682     if (editor && !qstrcmp(editor->kind(), Constants::C_FORMEDITOR)) {
683         FormWindowEditor *fw = qobject_cast<FormWindowEditor *>(editor);
684         QTC_ASSERT(fw, return);
685         fw->activate();
686         m_fwm->setActiveFormWindow(fw->formWindow());
687         m_actionGroupEditMode->setVisible(true);
688         m_modeActionSeparator->setVisible(true);
689         QDockWidget * const*dockWidgets = fw->dockWidgets();
690         for (int i = 0; i < Designer::Constants::DesignerSubWindowCount; ++i) {
691             if (m_designerSubWindowActions[i] != 0 && dockWidgets[i] != 0)
692                 m_designerSubWindowActions[i]->setAction(dockWidgets[i]->toggleViewAction());
693         }
694         m_lockAction->setEnabled(true);
695         m_lockAction->setChecked(fw->isLocked());
696         m_resetLayoutAction->setEnabled(true);
697     } else {
698         m_actionGroupEditMode->setVisible(false);
699         m_modeActionSeparator->setVisible(false);
700         m_fwm->setActiveFormWindow(0);
701         for (int i = 0; i < Designer::Constants::DesignerSubWindowCount; ++i) {
702             if (m_designerSubWindowActions[i] != 0)
703                 m_designerSubWindowActions[i]->setAction(0);
704         }
705         m_lockAction->setEnabled(false);
706         m_resetLayoutAction->setEnabled(false);
707     }
708 }
709
710 void FormEditorW::activeFormWindowChanged(QDesignerFormWindowInterface *afw)
711 {
712     if (Designer::Constants::Internal::debug)
713         qDebug() << Q_FUNC_INFO << afw << " of " << m_fwm->formWindowCount() << m_formWindows;
714
715     m_fwm->closeAllPreviews();
716
717     bool foundFormWindow = false;
718     // Display form selection handles only on active window
719     EditorList::const_iterator cend = m_formWindows.constEnd();
720     for (EditorList::const_iterator it = m_formWindows.constBegin(); it != cend ; ++it) {
721         FormWindowEditor *fwe = *it;
722         const bool active = fwe->formWindow() == afw;
723         if (active)
724             foundFormWindow = true;
725         fwe->updateFormWindowSelectionHandles(active);
726     }
727
728     m_actionPreview->setEnabled(foundFormWindow);
729     m_actionGroupPreviewInStyle->setEnabled(foundFormWindow);
730 }
731
732 FormWindowEditor *FormEditorW::activeFormWindow()
733 {
734     QDesignerFormWindowInterface *afw = m_fwm->activeFormWindow();
735     for (int i = 0; i < m_formWindows.count(); ++i) {
736         if (FormWindowEditor *fw = m_formWindows[i]) {
737             QDesignerFormWindowInterface *fwd = fw->formWindow();
738             if (fwd == afw) {
739                 return fw;
740             }
741         }
742     }
743     return 0;
744 }
745
746 void FormEditorW::activateEditMode(int id)
747 {
748     if (const int count = m_fwm->formWindowCount())
749         for (int i = 0; i <  count; i++)
750              m_fwm->formWindow(i)->setCurrentTool(id);
751 }
752
753 void FormEditorW::activateEditMode(QAction* a)
754 {
755     activateEditMode(a->data().toInt());
756 }
757
758 void FormEditorW::toolChanged(int t)
759 {
760     typedef QList<QAction *> ActionList;
761     if (const QAction *currentAction = m_actionGroupEditMode->checkedAction())
762         if (currentAction->data().toInt() == t)
763             return;
764     const ActionList actions = m_actionGroupEditMode->actions();
765     const ActionList::const_iterator cend = actions.constEnd();
766     for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
767         if ( (*it)->data().toInt() == t) {
768             (*it)->setChecked(true);
769             break;
770         }
771 }
772
773 void FormEditorW::setFormWindowLayoutLocked(bool locked)
774 {
775     FormWindowEditor *fwe = activeFormWindow();
776     if (fwe)
777         fwe->setLocked(locked);
778 }
779
780 void FormEditorW::resetToDefaultLayout()
781 {
782     FormWindowEditor *fwe = activeFormWindow();
783     if (fwe)
784         fwe->resetToDefaultLayout();
785 }
786
787 void FormEditorW::print()
788 {
789     // Printing code courtesy of designer_actions.cpp
790     QDesignerFormWindowInterface *fw = m_fwm->activeFormWindow();
791     if (!fw)
792         return;
793
794     const bool oldFullPage =  m_core->printer()->fullPage();
795     const QPrinter::Orientation oldOrientation =  m_core->printer()->orientation ();
796     m_core->printer()->setFullPage(false);
797     do {
798
799         // Grab the image to be able to a suggest suitable orientation
800         QString errorMessage;
801         const QPixmap pixmap = m_fwm->createPreviewPixmap(&errorMessage);
802         if (pixmap.isNull()) {
803             critical(tr("The image could not be created: %1").arg(errorMessage));
804             break;
805         }
806
807         const QSizeF pixmapSize = pixmap.size();
808         m_core->printer()->setOrientation( pixmapSize.width() > pixmapSize.height() ?  QPrinter::Landscape :  QPrinter::Portrait);
809
810         // Printer parameters
811         QPrintDialog dialog(m_core->printer(), fw);
812         if (!dialog.exec())
813            break;
814
815         const QCursor oldCursor = m_core->mainWindow()->cursor();
816         m_core->mainWindow()->setCursor(Qt::WaitCursor);
817         // Estimate of required scaling to make form look the same on screen and printer.
818         const double suggestedScaling = static_cast<double>(m_core->printer()->physicalDpiX()) /  static_cast<double>(fw->physicalDpiX());
819
820         QPainter painter(m_core->printer());
821         painter.setRenderHint(QPainter::SmoothPixmapTransform);
822
823         // Clamp to page
824         const QRectF page =  painter.viewport();
825         const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
826         const double scaling = qMin(suggestedScaling, maxScaling);
827
828         const double xOffset = page.left() + qMax(0.0, (page.size().width()  - scaling * pixmapSize.width())  / 2.0);
829         const double yOffset = page.top()  + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
830
831         // Draw.
832         painter.translate(xOffset, yOffset);
833         painter.scale(scaling, scaling);
834         painter.drawPixmap(0, 0, pixmap);
835         m_core->mainWindow()->setCursor(oldCursor);
836
837     } while (false);
838     m_core->printer()->setFullPage(oldFullPage);
839     m_core->printer()->setOrientation(oldOrientation);
840 }