OSDN Git Service

Internally use a fancy mainwindow in form editor.
[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://www.qtsoftware.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/QMenu>
70 #include <QtGui/QMainWindow>
71 #include <QtGui/QMessageBox>
72 #include <QtGui/QKeySequence>
73 #include <QtGui/QPrintDialog>
74 #include <QtGui/QPrinter>
75 #include <QtGui/QPainter>
76 #include <QtGui/QStatusBar>
77 #include <QtGui/QStyle>
78 #include <QtGui/QToolBar>
79
80 #include <QtCore/QDebug>
81 #include <QtCore/QSettings>
82
83 static const char *settingsGroup = "Designer";
84
85 #ifdef Q_OS_MAC
86     enum { osMac = 1 };
87 #else
88     enum { osMac = 0 };
89 #endif
90
91 /* Actions of the designer plugin:
92  * Designer provides a toolbar which is subject to a context change (to
93  * "edit mode" context) when it is focussed.
94  * In order to prevent its actions from being disabled/hidden by that context
95  * change, the actions are registered on the global context. In currentEditorChanged(),
96  * the ones that are present in the global edit menu are set visible/invisible manually.
97  * The designer context is currently used for Cut/Copy/Paste, etc. */
98
99 static inline QIcon designerIcon(const QString &iconName)
100 {
101     const QIcon icon = qdesigner_internal::createIconSet(iconName);
102     if (icon.isNull())
103         qWarning() << "Unable to locate " << iconName;
104     return icon;
105 }
106
107 // Create an action to activate a designer tool
108 static inline QAction *createEditModeAction(QActionGroup *ag,
109                                      const QList<int> &context,
110                                      Core::ActionManager *am,
111                                      Core::ActionContainer *medit,
112                                      const QString &actionName,
113                                      const QString &name,
114                                      int toolNumber,
115                                      const QString &iconName =  QString(),
116                                      const QString &keySequence = QString())
117 {
118     QAction *rc = new QAction(actionName, ag);
119     rc->setCheckable(true);
120     if (!iconName.isEmpty())
121          rc->setIcon(designerIcon(iconName));
122     Core::Command *command = am->registerAction(rc, name, context);
123     if (!keySequence.isEmpty())
124         command->setDefaultKeySequence(QKeySequence(keySequence));
125     medit->addAction(command, Core::Constants::G_EDIT_OTHER);
126     rc->setData(toolNumber);
127     ag->addAction(rc);
128     return rc;
129 }
130
131
132 // Create a menu separato
133 static inline QAction * createSeparator(QObject *parent,
134                                  Core::ActionManager *am,
135                                  const QList<int> &context,
136                                  Core::ActionContainer *container,
137                                  const QString &name = QString(),
138                                  const QString &group = QString())
139 {
140     QAction *actSeparator = new QAction(parent);
141     actSeparator->setSeparator(true);
142     Core::Command *command = am->registerAction(actSeparator, name, context);
143     container->addAction(command, group);
144     return actSeparator;
145 }
146
147 // Create a tool action
148 static inline void addToolAction(QAction *a,
149                    Core::ActionManager *am,
150                    const QList<int> &context,
151                    const QString &name,
152                    Core::ActionContainer *c1,
153                    const QString &keySequence = QString())
154 {
155     Core::Command *command = am->registerAction(a, name, context);
156     if (!keySequence.isEmpty())
157         command->setDefaultKeySequence(QKeySequence(keySequence));
158     c1->addAction(command);
159 }
160
161 // --------- FormEditorW
162
163 using namespace Designer::Internal;
164 using namespace Designer::Constants;
165
166 FormEditorW *FormEditorW::m_self = 0;
167
168 FormEditorW::FormEditorW() :
169     m_formeditor(QDesignerComponents::createFormEditor(0)),
170     m_integration(0),
171     m_fwm(0),
172     m_core(Core::ICore::instance()),
173     m_initStage(RegisterPlugins),
174     m_actionGroupEditMode(0),
175     m_actionPrint(0),
176     m_actionPreview(0),
177     m_actionGroupPreviewInStyle(0),
178     m_actionAboutPlugins(0)
179 {
180     if (Designer::Constants::Internal::debug)
181         qDebug() << Q_FUNC_INFO;
182     QTC_ASSERT(!m_self, return);
183     m_self = this;
184     QTC_ASSERT(m_core, return);
185
186     qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount,
187           static_cast<QWidget *>(0));
188
189     m_formeditor->setTopLevel(qobject_cast<QWidget *>(m_core->editorManager()));
190     m_formeditor->setSettingsManager(new SettingsManager());
191
192     m_fwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager*>(m_formeditor->formWindowManager());
193     QTC_ASSERT(m_fwm, return);
194
195     const int uid = m_core->uniqueIDManager()->uniqueIdentifier(QLatin1String(C_FORMEDITOR));
196     m_context << uid;
197
198     setupActions();
199
200     foreach (QDesignerOptionsPageInterface *designerPage, m_formeditor->optionsPages()) {
201         SettingsPage *settingsPage = new SettingsPage(designerPage);
202         ExtensionSystem::PluginManager::instance()->addObject(settingsPage);
203         m_settingsPages.append(settingsPage);
204     }
205     restoreSettings(m_core->settings());
206
207     connect(m_core->editorManager(), SIGNAL(currentEditorChanged(Core::IEditor *)),
208             this, SLOT(currentEditorChanged(Core::IEditor *)));
209 }
210
211 FormEditorW::~FormEditorW()
212 {
213     saveSettings(m_core->settings());
214
215     for (int i = 0; i < Designer::Constants::DesignerSubWindowCount; ++i)
216         delete m_designerSubWindows[i];
217
218     delete m_formeditor;
219     foreach (SettingsPage *settingsPage, m_settingsPages) {
220         ExtensionSystem::PluginManager::instance()->removeObject(settingsPage);
221         delete settingsPage;
222     }
223     delete  m_integration;
224     m_self = 0;
225 }
226
227 void FormEditorW::fullInit()
228 {
229     QTC_ASSERT(m_initStage == RegisterPlugins, return);
230     QTime *initTime = 0;
231     if (Designer::Constants::Internal::debug) {
232         initTime = new QTime;
233         initTime->start();
234     }
235
236     QDesignerComponents::createTaskMenu(m_formeditor, parent());
237     QDesignerComponents::initializePlugins(designerEditor());
238     QDesignerComponents::initializeResources();
239     initDesignerSubWindows();
240     m_integration = new QtCreatorIntegration(m_formeditor, this);
241     m_formeditor->setIntegration(m_integration);
242
243     /**
244      * This will initialize our TabOrder, Signals and slots and Buddy editors.
245      */
246     QList<QObject*> plugins = QPluginLoader::staticInstances();
247     plugins += m_formeditor->pluginManager()->instances();
248     foreach (QObject *plugin, plugins) {
249         if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
250             if (!formEditorPlugin->isInitialized())
251                 formEditorPlugin->initialize(m_formeditor);
252         }
253     }
254
255     if (m_actionAboutPlugins)
256         m_actionAboutPlugins->setEnabled(true);
257
258     if (Designer::Constants::Internal::debug) {
259         qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
260         delete initTime;
261     }
262
263     m_initStage = FullyInitialized;
264 }
265
266 void FormEditorW::initDesignerSubWindows()
267 {
268     qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount, static_cast<QWidget*>(0));
269
270     QDesignerWidgetBoxInterface *wb = QDesignerComponents::createWidgetBox(m_formeditor, 0);
271     wb->setWindowTitle(tr("Designer widgetbox"));
272     m_formeditor->setWidgetBox(wb);
273     m_designerSubWindows[WidgetBoxSubWindow] = wb;
274
275     QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, 0);
276     oi->setWindowTitle(tr("Object inspector"));
277     m_formeditor->setObjectInspector(oi);
278     m_designerSubWindows[ObjectInspectorSubWindow] = oi;
279
280     QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, 0);
281     pe->setWindowTitle(tr("Property editor"));
282     m_formeditor->setPropertyEditor(pe);
283     m_designerSubWindows[PropertyEditorSubWindow] = pe;
284
285     QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, 0);
286     se->setWindowTitle(tr("Signals and slots editor"));
287     m_designerSubWindows[SignalSlotEditorSubWindow] = se;
288
289     QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, 0);
290     ae->setWindowTitle(tr("Action editor"));
291     m_formeditor->setActionEditor(ae);
292     m_designerSubWindows[ActionEditorSubWindow] = ae;
293 }
294
295 void FormEditorW::ensureInitStage(InitializationStage s)
296 {
297     if (Designer::Constants::Internal::debug)
298         qDebug() << Q_FUNC_INFO << s;
299     if (!m_self)
300         m_self = new FormEditorW;
301     if (m_self->m_initStage >= s)
302         return;
303     QApplication::setOverrideCursor(Qt::WaitCursor);
304     m_self->fullInit();
305     QApplication::restoreOverrideCursor();
306 }
307
308 FormEditorW *FormEditorW::instance()
309 {
310     ensureInitStage(FullyInitialized);
311     return m_self;
312 }
313
314 void FormEditorW::deleteInstance()
315 {
316     delete m_self;
317 }
318
319 void FormEditorW::setupActions()
320 {
321     Core::ActionManager *am = m_core->actionManager();
322     Core::Command *command;
323
324     //menus
325     Core::ActionContainer *medit =
326         am->actionContainer(Core::Constants::M_EDIT);
327     Core::ActionContainer *mtools =
328         am->actionContainer(Core::Constants::M_TOOLS);
329
330     Core::ActionContainer *mformtools =
331         am->createMenu(M_FORMEDITOR);
332     mformtools->menu()->setTitle(tr("For&m editor"));
333     mtools->addMenu(mformtools);
334
335     //overridden actions
336     am->registerAction(m_fwm->actionUndo(), Core::Constants::UNDO, m_context);
337     am->registerAction(m_fwm->actionRedo(), Core::Constants::REDO, m_context);
338     am->registerAction(m_fwm->actionCut(), Core::Constants::CUT, m_context);
339     am->registerAction(m_fwm->actionCopy(), Core::Constants::COPY, m_context);
340     am->registerAction(m_fwm->actionPaste(), Core::Constants::PASTE, m_context);
341     am->registerAction(m_fwm->actionSelectAll(), Core::Constants::SELECTALL, m_context);
342
343     m_actionPrint = new QAction(this);
344     am->registerAction(m_actionPrint, Core::Constants::PRINT, m_context);
345     connect(m_actionPrint, SIGNAL(triggered()), this, SLOT(print()));
346
347     //'delete' action
348     command = am->registerAction(m_fwm->actionDelete(), QLatin1String("FormEditor.Edit.Delete"), m_context);
349     command->setDefaultKeySequence(QKeySequence::Delete);
350     command->setAttribute(Core::Command::CA_Hide);
351     medit->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
352
353     QList<int> globalcontext;
354     globalcontext << m_core->uniqueIDManager()->uniqueIdentifier(Core::Constants::C_GLOBAL);
355
356     m_actionGroupEditMode = new QActionGroup(this);
357     m_actionGroupEditMode->setExclusive(true);
358     connect(m_actionGroupEditMode, SIGNAL(triggered(QAction*)), this, SLOT(activateEditMode(QAction*)));
359
360     m_modeActionSeparator = new QAction(this);
361     m_modeActionSeparator->setSeparator(true);
362     command = am->registerAction(m_modeActionSeparator, QLatin1String("FormEditor.Sep.ModeActions"), globalcontext);
363     medit->addAction(command, Core::Constants::G_EDIT_OTHER);
364
365     m_toolActionIds.push_back(QLatin1String("FormEditor.WidgetEditor"));
366     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
367                          tr("Edit widgets"), m_toolActionIds.back(),
368                          EditModeWidgetEditor, QLatin1String("widgettool.png"), tr("F3"));
369
370     m_toolActionIds.push_back(QLatin1String("FormEditor.SignalsSlotsEditor"));
371     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
372                          tr("Edit signals/slots"), m_toolActionIds.back(),
373                          EditModeSignalsSlotEditor, QLatin1String("signalslottool.png"), tr("F4"));
374
375     m_toolActionIds.push_back(QLatin1String("FormEditor.BuddyEditor"));
376     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
377                          tr("Edit buddies"), m_toolActionIds.back(),
378                          EditModeBuddyEditor, QLatin1String("buddytool.png"));
379
380     m_toolActionIds.push_back(QLatin1String("FormEditor.TabOrderEditor"));
381     createEditModeAction(m_actionGroupEditMode, globalcontext, am, medit,
382                          tr("Edit tab order"),  m_toolActionIds.back(),
383                          EditModeTabOrderEditor, QLatin1String("tabordertool.png"));
384
385     //tool actions
386     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutHorizontally"));
387     const QString horizLayoutShortcut = osMac ? tr("Meta+H") : tr("Ctrl+H");
388     addToolAction(m_fwm->actionHorizontalLayout(), am, globalcontext,
389                   m_toolActionIds.back(), mformtools, horizLayoutShortcut);
390
391     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutVertically"));
392     const QString vertLayoutShortcut = osMac ? tr("Meta+L") : tr("Ctrl+L");
393     addToolAction(m_fwm->actionVerticalLayout(), am, globalcontext,
394                   m_toolActionIds.back(),  mformtools, vertLayoutShortcut);
395
396     m_toolActionIds.push_back(QLatin1String("FormEditor.SplitHorizontal"));
397     addToolAction(m_fwm->actionSplitHorizontal(), am, globalcontext,
398                   m_toolActionIds.back(), mformtools);
399
400     m_toolActionIds.push_back(QLatin1String("FormEditor.SplitVertical"));
401     addToolAction(m_fwm->actionSplitVertical(), am, globalcontext,
402                   m_toolActionIds.back(), mformtools);
403
404     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutForm"));
405     addToolAction(m_fwm->actionFormLayout(), am, globalcontext,
406                   m_toolActionIds.back(),  mformtools);
407
408     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutGrid"));
409     const QString gridShortcut = osMac ? tr("Meta+G") : tr("Ctrl+G");
410     addToolAction(m_fwm->actionGridLayout(), am, globalcontext,
411                   m_toolActionIds.back(),  mformtools, gridShortcut);
412
413     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutBreak"));
414     addToolAction(m_fwm->actionBreakLayout(), am, globalcontext,
415                   m_toolActionIds.back(), mformtools);
416
417     m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutAdjustSize"));
418     const QString adjustShortcut = osMac ? tr("Meta+J") : tr("Ctrl+J");
419     addToolAction(m_fwm->actionAdjustSize(), am, globalcontext,
420                   m_toolActionIds.back(),  mformtools, adjustShortcut);
421
422     m_toolActionIds.push_back(QLatin1String("FormEditor.SimplifyLayout"));
423     addToolAction(m_fwm->actionSimplifyLayout(), am, globalcontext,
424                   m_toolActionIds.back(),  mformtools);
425
426     createSeparator(this, am, m_context, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator1"));
427
428     addToolAction(m_fwm->actionLower(), am, globalcontext,
429                   QLatin1String("FormEditor.Lower"), mformtools);
430
431     addToolAction(m_fwm->actionRaise(), am, globalcontext,
432                   QLatin1String("FormEditor.Raise"), mformtools);
433
434     // Commands that do not go into the editor toolbar
435     createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator2"));
436
437     m_actionPreview = m_fwm->actionDefaultPreview();
438     QTC_ASSERT(m_actionPreview, return);
439     addToolAction(m_actionPreview,  am,  globalcontext,
440                    QLatin1String("FormEditor.Preview"), mformtools, tr("Ctrl+Alt+R"));
441
442     // Preview in style...
443     m_actionGroupPreviewInStyle = m_fwm->actionGroupPreviewInStyle();
444     mformtools->addMenu(createPreviewStyleMenu(am, m_actionGroupPreviewInStyle));
445
446     // Form settings
447     createSeparator(this, am, m_context,  medit, QLatin1String("FormEditor.Edit.Separator2"), Core::Constants::G_EDIT_OTHER);
448
449     createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator3"));
450     QAction *actionFormSettings = m_fwm->actionShowFormWindowSettingsDialog();
451     addToolAction(actionFormSettings, am, globalcontext, QLatin1String("FormEditor.FormSettings"), mformtools);
452
453 #if QT_VERSION > 0x040500
454     createSeparator(this, am, globalcontext, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator4"));
455     m_actionAboutPlugins = new QAction(tr("About Qt Designer plugins...."), this);
456     addToolAction(m_actionAboutPlugins,  am,  globalcontext,
457                    QLatin1String("FormEditor.AboutPlugins"), mformtools);
458     connect(m_actionAboutPlugins,  SIGNAL(triggered()), m_fwm, SLOT(aboutPlugins()));
459     m_actionAboutPlugins->setEnabled(false);
460 #endif
461
462     // FWM
463     connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface *)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface *)));
464 }
465
466
467 QToolBar *FormEditorW::createEditorToolBar() const
468 {
469     QToolBar *toolBar = new QToolBar;
470     Core::ActionManager *am = m_core->actionManager();
471     const QStringList::const_iterator cend = m_toolActionIds.constEnd();
472     for (QStringList::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
473         Core::Command *cmd = am->command(*it);
474         QTC_ASSERT(cmd, continue);
475         QAction *action = cmd->action();
476         if (!action->icon().isNull()) // Simplify grid has no action yet
477             toolBar->addAction(action);
478     }
479     int size = toolBar->style()->pixelMetric(QStyle::PM_SmallIconSize);
480     toolBar->setIconSize(QSize(size, size));
481     toolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
482     return toolBar;
483 }
484
485 Core::ActionContainer *FormEditorW::createPreviewStyleMenu(Core::ActionManager *am,
486                                                             QActionGroup *actionGroup)
487 {
488     const QString menuId = QLatin1String(M_FORMEDITOR_PREVIEW);
489     Core::ActionContainer *menuPreviewStyle = am->createMenu(menuId);
490     menuPreviewStyle->menu()->setTitle(tr("Preview in"));
491
492     // The preview menu is a list of invisible actions for the embedded design
493     // device profiles (integer data) followed by a separator and the styles
494     // (string data). Make device profiles update their text and hide them
495     // in the configuration dialog.
496     const QList<QAction*> actions = actionGroup->actions();
497
498     const QString deviceProfilePrefix = QLatin1String("DeviceProfile");
499     const QChar dot = QLatin1Char('.');
500
501     foreach (QAction* a, actions) {
502         QString name = menuId;
503         name += dot;
504         const QVariant data = a->data();
505         const bool isDeviceProfile = data.type() == QVariant::Int;
506         if (isDeviceProfile) {
507             name += deviceProfilePrefix;
508             name += dot;
509         }
510         name += data.toString();
511         Core::Command *command = am->registerAction(a, name, m_context);
512         if (isDeviceProfile) {
513             command->setAttribute(Core::Command::CA_UpdateText);
514             command->setAttribute(Core::Command::CA_NonConfigureable);
515         }
516         menuPreviewStyle->addAction(command);
517     }
518     return menuPreviewStyle;
519 }
520
521 void FormEditorW::saveSettings(QSettings *s)
522 {
523     s->beginGroup(settingsGroup);
524     EditorWidget::saveState(s);
525     s->endGroup();
526 }
527
528 void FormEditorW::restoreSettings(QSettings *s)
529 {
530     s->beginGroup(settingsGroup);
531     EditorWidget::restoreState(s);
532     s->endGroup();
533 }
534
535
536 void FormEditorW::critical(const QString &errorMessage)
537 {
538     QMessageBox::critical(m_core->mainWindow(), tr("Designer"),  errorMessage);
539 }
540
541 FormWindowEditor *FormEditorW::createFormWindowEditor(QWidget* parentWidget)
542 {
543     m_fwm->closeAllPreviews();
544     QDesignerFormWindowInterface *form = m_fwm->createFormWindow(0);
545     connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int)));
546     qdesigner_internal::FormWindowBase::setupDefaultAction(form);
547     FormWindowEditor *fww = new FormWindowEditor(m_context, form, parentWidget);
548     // Store a pointer to all form windows so we can unselect
549     // all other formwindows except the active one.
550     m_formWindows.append(fww);
551     connect(fww, SIGNAL(destroyed()), this, SLOT(editorDestroyed()));
552     return fww;
553 }
554
555 void FormEditorW::editorDestroyed()
556 {
557     QObject *source = sender();
558
559     if (Designer::Constants::Internal::debug)
560         qDebug() << Q_FUNC_INFO << source;
561
562     for (EditorList::iterator it = m_formWindows.begin(); it != m_formWindows.end(); ) {
563         if (*it == source) {
564             it = m_formWindows.erase(it);
565             break;
566         } else {
567             ++it;
568         }
569     }
570 }
571
572 void FormEditorW::currentEditorChanged(Core::IEditor *editor)
573 {
574     if (Designer::Constants::Internal::debug)
575         qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
576
577     // Deactivate Designer if a non-form is being edited
578     if (editor && !qstrcmp(editor->kind(), Constants::C_FORMEDITOR)) {
579         FormWindowEditor *fw = qobject_cast<FormWindowEditor *>(editor);
580         QTC_ASSERT(fw, return);
581         fw->activate();
582         m_fwm->setActiveFormWindow(fw->formWindow());
583         m_actionGroupEditMode->setVisible(true);
584         m_modeActionSeparator->setVisible(true);
585     } else {
586         m_actionGroupEditMode->setVisible(false);
587         m_modeActionSeparator->setVisible(false);
588         m_fwm->setActiveFormWindow(0);
589     }
590 }
591
592 void FormEditorW::activeFormWindowChanged(QDesignerFormWindowInterface *afw)
593 {
594     if (Designer::Constants::Internal::debug)
595         qDebug() << Q_FUNC_INFO << afw << " of " << m_fwm->formWindowCount() << m_formWindows;
596
597     m_fwm->closeAllPreviews();
598
599     bool foundFormWindow = false;
600     // Display form selection handles only on active window
601     EditorList::const_iterator cend = m_formWindows.constEnd();
602     for (EditorList::const_iterator it = m_formWindows.constBegin(); it != cend ; ++it) {
603         FormWindowEditor *fwe = *it;
604         const bool active = fwe->formWindow() == afw;
605         if (active)
606             foundFormWindow = true;
607         fwe->updateFormWindowSelectionHandles(active);
608     }
609
610     m_actionPreview->setEnabled(foundFormWindow);
611     m_actionGroupPreviewInStyle->setEnabled(foundFormWindow);
612 }
613
614 FormWindowEditor *FormEditorW::activeFormWindow()
615 {
616     QDesignerFormWindowInterface *afw = m_fwm->activeFormWindow();
617     for (int i = 0; i < m_formWindows.count(); ++i) {
618         if (FormWindowEditor *fw = m_formWindows[i]) {
619             QDesignerFormWindowInterface *fwd = fw->formWindow();
620             if (fwd == afw) {
621                 return fw;
622             }
623         }
624     }
625     return 0;
626 }
627
628 void FormEditorW::activateEditMode(int id)
629 {
630     if (const int count = m_fwm->formWindowCount())
631         for (int i = 0; i <  count; i++)
632              m_fwm->formWindow(i)->setCurrentTool(id);
633 }
634
635 void FormEditorW::activateEditMode(QAction* a)
636 {
637     activateEditMode(a->data().toInt());
638 }
639
640 void FormEditorW::toolChanged(int t)
641 {
642     typedef QList<QAction *> ActionList;
643     if (const QAction *currentAction = m_actionGroupEditMode->checkedAction())
644         if (currentAction->data().toInt() == t)
645             return;
646     const ActionList actions = m_actionGroupEditMode->actions();
647     const ActionList::const_iterator cend = actions.constEnd();
648     for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
649         if ( (*it)->data().toInt() == t) {
650             (*it)->setChecked(true);
651             break;
652         }
653 }
654
655 void FormEditorW::print()
656 {
657     // Printing code courtesy of designer_actions.cpp
658     QDesignerFormWindowInterface *fw = m_fwm->activeFormWindow();
659     if (!fw)
660         return;
661
662     const bool oldFullPage =  m_core->printer()->fullPage();
663     const QPrinter::Orientation oldOrientation =  m_core->printer()->orientation ();
664     m_core->printer()->setFullPage(false);
665     do {
666
667         // Grab the image to be able to a suggest suitable orientation
668         QString errorMessage;
669         const QPixmap pixmap = m_fwm->createPreviewPixmap(&errorMessage);
670         if (pixmap.isNull()) {
671             critical(tr("The image could not be created: %1").arg(errorMessage));
672             break;
673         }
674
675         const QSizeF pixmapSize = pixmap.size();
676         m_core->printer()->setOrientation( pixmapSize.width() > pixmapSize.height() ?  QPrinter::Landscape :  QPrinter::Portrait);
677
678         // Printer parameters
679         QPrintDialog dialog(m_core->printer(), fw);
680         if (!dialog.exec())
681            break;
682
683         const QCursor oldCursor = m_core->mainWindow()->cursor();
684         m_core->mainWindow()->setCursor(Qt::WaitCursor);
685         // Estimate of required scaling to make form look the same on screen and printer.
686         const double suggestedScaling = static_cast<double>(m_core->printer()->physicalDpiX()) /  static_cast<double>(fw->physicalDpiX());
687
688         QPainter painter(m_core->printer());
689         painter.setRenderHint(QPainter::SmoothPixmapTransform);
690
691         // Clamp to page
692         const QRectF page =  painter.viewport();
693         const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
694         const double scaling = qMin(suggestedScaling, maxScaling);
695
696         const double xOffset = page.left() + qMax(0.0, (page.size().width()  - scaling * pixmapSize.width())  / 2.0);
697         const double yOffset = page.top()  + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
698
699         // Draw.
700         painter.translate(xOffset, yOffset);
701         painter.scale(scaling, scaling);
702         painter.drawPixmap(0, 0, pixmap);
703         m_core->mainWindow()->setCursor(oldCursor);
704
705     } while (false);
706     m_core->printer()->setFullPage(oldFullPage);
707     m_core->printer()->setOrientation(oldOrientation);
708 }