1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
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.
16 ** GNU Lesser General Public License Usage
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.
25 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
28 **************************************************************************/
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 "editordata.h"
37 #include "qtcreatorintegration.h"
38 #include "designerxmleditor.h"
39 #include "designercontext.h"
40 #include "editorwidget.h"
41 #include "resourcehandler.h"
42 #include <widgethost.h>
44 #include <coreplugin/editortoolbar.h>
45 #include <coreplugin/designmode.h>
46 #include <coreplugin/coreconstants.h>
47 #include <coreplugin/icore.h>
48 #include <coreplugin/helpmanager.h>
49 #include <coreplugin/uniqueidmanager.h>
50 #include <coreplugin/actionmanager/actionmanager.h>
51 #include <coreplugin/actionmanager/actioncontainer.h>
52 #include <coreplugin/actionmanager/command.h>
53 #include <coreplugin/editormanager/editormanager.h>
54 #include <coreplugin/minisplitter.h>
55 #include <coreplugin/outputpane.h>
56 #include <texteditor/texteditorsettings.h>
57 #include <extensionsystem/pluginmanager.h>
58 #include <utils/qtcassert.h>
60 #include <QtDesigner/QDesignerFormEditorPluginInterface>
61 #include "qt_private/pluginmanager_p.h"
63 #include "qt_private/iconloader_p.h" // createIconSet
64 #include "qt_private/qdesigner_formwindowmanager_p.h"
65 #include "qt_private/formwindowbase_p.h"
66 #include <QtDesigner/QDesignerFormEditorInterface>
67 #include <QtDesigner/QDesignerComponents>
69 #include <QtDesigner/QDesignerWidgetBoxInterface>
70 #include <QtDesigner/abstractobjectinspector.h>
71 #include <QtDesigner/QDesignerPropertyEditorInterface>
72 #include <QtDesigner/QDesignerActionEditorInterface>
73 #include <QtDesigner/QDesignerFormEditorInterface>
75 #include <QtGui/QAction>
76 #include <QtGui/QActionGroup>
77 #include <QtGui/QApplication>
78 #include <QtGui/QCursor>
79 #include <QtGui/QDockWidget>
80 #include <QtGui/QMenu>
81 #include <QtGui/QMainWindow>
82 #include <QtGui/QMessageBox>
83 #include <QtGui/QKeySequence>
84 #include <QtGui/QPrintDialog>
85 #include <QtGui/QPrinter>
86 #include <QtGui/QPainter>
87 #include <QtGui/QStyle>
88 #include <QtGui/QToolBar>
89 #include <QtGui/QVBoxLayout>
91 #include <QtCore/QDebug>
92 #include <QtCore/QSettings>
93 #include <QtCore/QSignalMapper>
94 #include <QtCore/QPluginLoader>
95 #include <QtCore/QTime>
97 static const char settingsGroup[] = "Designer";
105 /* Actions of the designer plugin:
106 * Designer provides a toolbar which is subject to a context change (to
107 * "edit mode" context) when it is focused.
108 * In order to prevent its actions from being disabled/hidden by that context
109 * change, the actions are registered on the global context. In currentEditorChanged(),
110 * the ones that are present in the global edit menu are set visible/invisible manually.
111 * The designer context is currently used for Cut/Copy/Paste, etc. */
113 static inline QIcon designerIcon(const QString &iconName)
115 const QIcon icon = qdesigner_internal::createIconSet(iconName);
117 qWarning() << "Unable to locate " << iconName;
121 // Create a menu separator
122 static inline QAction *createSeparator(QObject *parent,
123 Core::ActionManager *am,
124 const QList<int> &context,
125 Core::ActionContainer *container,
126 const QString &name = QString(),
127 const QString &group = QString())
129 QAction *actSeparator = new QAction(parent);
130 actSeparator->setSeparator(true);
131 Core::Command *command = am->registerAction(actSeparator, name, context);
132 container->addAction(command, group);
136 using namespace Designer::Constants;
141 // --------- FormEditorW
143 FormEditorW *FormEditorW::m_self = 0;
145 FormEditorW::FormEditorW() :
146 m_formeditor(QDesignerComponents::createFormEditor(0)),
149 m_core(Core::ICore::instance()),
150 m_initStage(RegisterPlugins),
151 m_actionGroupEditMode(0),
154 m_actionGroupPreviewInStyle(0),
155 m_previewInStyleMenu(0),
156 m_actionAboutPlugins(0),
157 m_shortcutMapper(new QSignalMapper(this)),
165 if (Designer::Constants::Internal::debug)
166 qDebug() << Q_FUNC_INFO;
167 QTC_ASSERT(!m_self, return);
169 QTC_ASSERT(m_core, return);
171 qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount,
172 static_cast<QWidget *>(0));
174 m_formeditor->setTopLevel(qobject_cast<QWidget *>(m_core->editorManager()));
175 m_formeditor->setSettingsManager(new SettingsManager());
177 m_fwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager*>(m_formeditor->formWindowManager());
178 QTC_ASSERT(m_fwm, return);
180 Core::UniqueIDManager *idMan = Core::UniqueIDManager::instance();
181 m_contexts << idMan->uniqueIdentifier(QLatin1String(Designer::Constants::C_FORMEDITOR));
185 foreach (QDesignerOptionsPageInterface *designerPage, m_formeditor->optionsPages()) {
186 SettingsPage *settingsPage = new SettingsPage(designerPage);
187 ExtensionSystem::PluginManager::instance()->addObject(settingsPage);
188 m_settingsPages.append(settingsPage);
191 connect(m_core->editorManager(), SIGNAL(currentEditorChanged(Core::IEditor *)),
192 this, SLOT(currentEditorChanged(Core::IEditor *)));
193 connect(m_shortcutMapper, SIGNAL(mapped(QObject *)),
194 this, SLOT(updateShortcut(QObject *)));
197 FormEditorW::~FormEditorW()
200 m_core->removeContextObject(m_context);
201 if (m_initStage == FullyInitialized) {
202 if (QSettings *s = m_core->settings()) {
203 m_core->settings()->beginGroup(settingsGroup);
204 m_editorWidget->saveSettings(s);
208 m_designMode->unregisterDesignWidget(m_modeWidget);
214 foreach (SettingsPage *settingsPage, m_settingsPages) {
215 ExtensionSystem::PluginManager::instance()->removeObject(settingsPage);
218 delete m_integration;
223 // Add an actioon to toggle the view state of a dock window
224 void FormEditorW::addDockViewAction(Core::ActionManager *am,
225 Core::ActionContainer *viewMenu,
226 int index, const QList<int> &context,
227 const QString &title, const QString &id)
229 if (const QDockWidget *dw = m_editorWidget->designerDockWidgets()[index]) {
230 QAction *action = dw->toggleViewAction();
231 action->setText(title);
232 Core::Command *cmd = addToolAction(action, am, context, id, viewMenu, QString());
233 cmd->setAttribute(Core::Command::CA_Hide);
237 void FormEditorW::setupViewActions()
239 // Populate "View" menu of form editor menu
240 Core::ActionManager *am = m_core->actionManager();
241 Core::ActionContainer *viewMenu = am->actionContainer(QLatin1String(Core::Constants::M_WINDOW_VIEWS));
242 QTC_ASSERT(viewMenu, return)
244 addDockViewAction(am, viewMenu, WidgetBoxSubWindow, m_contexts,
245 tr("Widget box"), QLatin1String("FormEditor.WidgetBox"));
247 addDockViewAction(am, viewMenu, ObjectInspectorSubWindow, m_contexts,
248 tr("Object Inspector"), QLatin1String("FormEditor.ObjectInspector"));
250 addDockViewAction(am, viewMenu, PropertyEditorSubWindow, m_contexts,
251 tr("Property Editor"), QLatin1String("FormEditor.PropertyEditor"));
253 addDockViewAction(am, viewMenu, SignalSlotEditorSubWindow, m_contexts,
254 tr("Signals && Slots Editor"), QLatin1String("FormEditor.SignalsAndSlotsEditor"));
256 addDockViewAction(am, viewMenu, ActionEditorSubWindow, m_contexts,
257 tr("Action Editor"), QLatin1String("FormEditor.ActionEditor"));
259 Core::Command *cmd = addToolAction(m_editorWidget->menuSeparator1(), am, m_contexts, QLatin1String("FormEditor.SeparatorLock"), viewMenu, QString());
260 cmd->setAttribute(Core::Command::CA_Hide);
262 cmd = addToolAction(m_editorWidget->toggleLockedAction(), am, m_contexts, QLatin1String("FormEditor.Locked"), viewMenu, QString());
263 cmd->setAttribute(Core::Command::CA_Hide);
265 cmd = addToolAction(m_editorWidget->menuSeparator2(), am, m_contexts, QLatin1String("FormEditor.SeparatorReset"), viewMenu, QString());
266 cmd->setAttribute(Core::Command::CA_Hide);
268 cmd = addToolAction(m_editorWidget->resetLayoutAction(), am, m_contexts, QLatin1String("FormEditor.ResetToDefaultLayout"), viewMenu, QString());
269 connect(m_editorWidget, SIGNAL(resetLayout()), m_editorWidget, SLOT(resetToDefaultLayout()));
270 cmd->setAttribute(Core::Command::CA_Hide);
273 void FormEditorW::fullInit()
275 QTC_ASSERT(m_initStage == RegisterPlugins, return);
277 if (Designer::Constants::Internal::debug) {
278 initTime = new QTime;
282 QDesignerComponents::createTaskMenu(m_formeditor, parent());
283 QDesignerComponents::initializePlugins(designerEditor());
284 QDesignerComponents::initializeResources();
285 initDesignerSubWindows();
286 m_integration = new QtCreatorIntegration(m_formeditor, this);
287 m_formeditor->setIntegration(m_integration);
288 // Connect Qt Designer help request to HelpManager.
289 connect(m_integration, SIGNAL(creatorHelpRequested(QUrl)),
290 Core::HelpManager::instance(), SIGNAL(helpRequested(QUrl)));
293 * This will initialize our TabOrder, Signals and slots and Buddy editors.
295 QList<QObject*> plugins = QPluginLoader::staticInstances();
296 plugins += m_formeditor->pluginManager()->instances();
297 foreach (QObject *plugin, plugins) {
298 if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
299 if (!formEditorPlugin->isInitialized())
300 formEditorPlugin->initialize(m_formeditor);
304 if (m_actionAboutPlugins)
305 m_actionAboutPlugins->setEnabled(true);
307 if (Designer::Constants::Internal::debug) {
308 qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
312 connect(m_core->editorManager()->instance(), SIGNAL(editorsClosed(QList<Core::IEditor*>)),
313 SLOT(closeFormEditorsForXmlEditors(QList<Core::IEditor*>)));
314 // Nest toolbar and editor widget
315 m_editorWidget = new EditorWidget(this);
316 QSettings *settings = m_core->settings();
317 settings->beginGroup(settingsGroup);
318 m_editorWidget->restoreSettings(settings);
319 settings->endGroup();
321 m_editorToolBar = createEditorToolBar();
322 m_toolBar = Core::EditorManager::createToolBar();
323 m_toolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
324 m_toolBar->setNavigationVisible(false);
325 m_toolBar->addCenterToolBar(m_editorToolBar);
327 m_designMode = ExtensionSystem::PluginManager::instance()->getObject<Core::DesignMode>();
328 m_modeWidget = new QWidget;
329 m_modeWidget->setObjectName(QLatin1String("DesignerModeWidget"));
330 QVBoxLayout *layout = new QVBoxLayout;
331 layout->setMargin(0);
332 layout->setSpacing(0);
333 layout->addWidget(m_toolBar);
334 // Avoid mode switch to 'Edit' mode when the application started by
335 // 'Run' in 'Design' mode emits output.
336 Core::MiniSplitter *splitter = new Core::MiniSplitter(Qt::Vertical);
337 splitter->addWidget(m_editorWidget);
338 splitter->addWidget(new Core::OutputPanePlaceHolder(m_designMode, splitter));
339 layout->addWidget(splitter);
340 m_modeWidget->setLayout(layout);
342 Core::UniqueIDManager *idMan = Core::UniqueIDManager::instance();
343 int editorManagerContext = idMan->uniqueIdentifier(QLatin1String(Core::Constants::C_EDITORMANAGER));
345 m_context = new DesignerContext(QList<int>() << m_contexts << editorManagerContext, m_modeWidget, this);
346 m_core->addContextObject(m_context);
348 m_designMode->registerDesignWidget(m_modeWidget, QStringList(QLatin1String(FORM_MIMETYPE)), m_contexts);
352 m_initStage = FullyInitialized;
355 void FormEditorW::initDesignerSubWindows()
357 qFill(m_designerSubWindows, m_designerSubWindows + Designer::Constants::DesignerSubWindowCount, static_cast<QWidget*>(0));
359 QDesignerWidgetBoxInterface *wb = QDesignerComponents::createWidgetBox(m_formeditor, 0);
360 wb->setWindowTitle(tr("Widget Box"));
361 wb->setObjectName(QLatin1String("WidgetBox"));
362 m_formeditor->setWidgetBox(wb);
363 m_designerSubWindows[WidgetBoxSubWindow] = wb;
365 QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, 0);
366 oi->setWindowTitle(tr("Object Inspector"));
367 oi->setObjectName(QLatin1String("ObjectInspector"));
368 m_formeditor->setObjectInspector(oi);
369 m_designerSubWindows[ObjectInspectorSubWindow] = oi;
371 QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, 0);
372 pe->setWindowTitle(tr("Property Editor"));
373 pe->setObjectName(QLatin1String("PropertyEditor"));
374 m_formeditor->setPropertyEditor(pe);
375 m_designerSubWindows[PropertyEditorSubWindow] = pe;
377 QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, 0);
378 se->setWindowTitle(tr("Signals && Slots Editor"));
379 se->setObjectName(QLatin1String("SignalsAndSlotsEditor"));
380 m_designerSubWindows[SignalSlotEditorSubWindow] = se;
382 QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, 0);
383 ae->setWindowTitle(tr("Action Editor"));
384 ae->setObjectName(QLatin1String("ActionEditor"));
385 m_formeditor->setActionEditor(ae);
386 m_designerSubWindows[ActionEditorSubWindow] = ae;
389 void FormEditorW::ensureInitStage(InitializationStage s)
391 if (Designer::Constants::Internal::debug)
392 qDebug() << Q_FUNC_INFO << s;
394 m_self = new FormEditorW;
395 if (m_self->m_initStage >= s)
397 QApplication::setOverrideCursor(Qt::WaitCursor);
399 QApplication::restoreOverrideCursor();
402 FormEditorW *FormEditorW::instance()
404 ensureInitStage(FullyInitialized);
408 void FormEditorW::deleteInstance()
413 void FormEditorW::setupActions()
415 Core::ActionManager *am = m_core->actionManager();
416 Core::Command *command;
419 Core::ActionContainer *medit =
420 am->actionContainer(Core::Constants::M_EDIT);
421 Core::ActionContainer *mtools =
422 am->actionContainer(Core::Constants::M_TOOLS);
424 Core::ActionContainer *mformtools =
425 am->createMenu(M_FORMEDITOR);
426 mformtools->menu()->setTitle(tr("For&m Editor"));
427 mtools->addMenu(mformtools);
430 bindShortcut(am->registerAction(m_fwm->actionUndo(), Core::Constants::UNDO, m_contexts), m_fwm->actionUndo());
431 bindShortcut(am->registerAction(m_fwm->actionRedo(), Core::Constants::REDO, m_contexts), m_fwm->actionRedo());
432 bindShortcut(am->registerAction(m_fwm->actionCut(), Core::Constants::CUT, m_contexts), m_fwm->actionCut());
433 bindShortcut(am->registerAction(m_fwm->actionCopy(), Core::Constants::COPY, m_contexts), m_fwm->actionCopy());
434 bindShortcut(am->registerAction(m_fwm->actionPaste(), Core::Constants::PASTE, m_contexts), m_fwm->actionPaste());
435 bindShortcut(am->registerAction(m_fwm->actionSelectAll(), Core::Constants::SELECTALL, m_contexts), m_fwm->actionSelectAll());
437 m_actionPrint = new QAction(this);
438 bindShortcut(am->registerAction(m_actionPrint, Core::Constants::PRINT, m_contexts), m_actionPrint);
439 connect(m_actionPrint, SIGNAL(triggered()), this, SLOT(print()));
441 //'delete' action. Do not set a shortcut as Designer handles
442 // the 'Delete' key by event filter. Setting a shortcut triggers
443 // buggy behaviour on Mac (Pressing Delete in QLineEdit removing the widget).
444 command = am->registerAction(m_fwm->actionDelete(), QLatin1String("FormEditor.Edit.Delete"), m_contexts);
445 bindShortcut(command, m_fwm->actionDelete());
446 command->setAttribute(Core::Command::CA_Hide);
447 medit->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
449 m_actionGroupEditMode = new QActionGroup(this);
450 m_actionGroupEditMode->setExclusive(true);
451 connect(m_actionGroupEditMode, SIGNAL(triggered(QAction*)), this, SLOT(activateEditMode(QAction*)));
453 m_modeActionSeparator = new QAction(this);
454 m_modeActionSeparator->setSeparator(true);
455 command = am->registerAction(m_modeActionSeparator, QLatin1String("FormEditor.Sep.ModeActions"), m_contexts);
456 medit->addAction(command, Core::Constants::G_EDIT_OTHER);
458 m_toolActionIds.push_back(QLatin1String("FormEditor.WidgetEditor"));
459 createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
460 tr("Edit Widgets"), m_toolActionIds.back(),
461 EditModeWidgetEditor, QLatin1String("widgettool.png"), tr("F3"));
463 m_toolActionIds.push_back(QLatin1String("FormEditor.SignalsSlotsEditor"));
464 createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
465 tr("Edit Signals/Slots"), m_toolActionIds.back(),
466 EditModeSignalsSlotEditor, QLatin1String("signalslottool.png"), tr("F4"));
468 m_toolActionIds.push_back(QLatin1String("FormEditor.BuddyEditor"));
469 createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
470 tr("Edit Buddies"), m_toolActionIds.back(),
471 EditModeBuddyEditor, QLatin1String("buddytool.png"));
473 m_toolActionIds.push_back(QLatin1String("FormEditor.TabOrderEditor"));
474 createEditModeAction(m_actionGroupEditMode, m_contexts, am, medit,
475 tr("Edit Tab Order"), m_toolActionIds.back(),
476 EditModeTabOrderEditor, QLatin1String("tabordertool.png"));
479 m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutHorizontally"));
480 const QString horizLayoutShortcut = osMac ? tr("Meta+H") : tr("Ctrl+H");
481 addToolAction(m_fwm->actionHorizontalLayout(), am, m_contexts,
482 m_toolActionIds.back(), mformtools, horizLayoutShortcut);
484 m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutVertically"));
485 const QString vertLayoutShortcut = osMac ? tr("Meta+L") : tr("Ctrl+L");
486 addToolAction(m_fwm->actionVerticalLayout(), am, m_contexts,
487 m_toolActionIds.back(), mformtools, vertLayoutShortcut);
489 m_toolActionIds.push_back(QLatin1String("FormEditor.SplitHorizontal"));
490 addToolAction(m_fwm->actionSplitHorizontal(), am, m_contexts,
491 m_toolActionIds.back(), mformtools);
493 m_toolActionIds.push_back(QLatin1String("FormEditor.SplitVertical"));
494 addToolAction(m_fwm->actionSplitVertical(), am, m_contexts,
495 m_toolActionIds.back(), mformtools);
497 m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutForm"));
498 addToolAction(m_fwm->actionFormLayout(), am, m_contexts,
499 m_toolActionIds.back(), mformtools);
501 m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutGrid"));
502 const QString gridShortcut = osMac ? tr("Meta+G") : tr("Ctrl+G");
503 addToolAction(m_fwm->actionGridLayout(), am, m_contexts,
504 m_toolActionIds.back(), mformtools, gridShortcut);
506 m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutBreak"));
507 addToolAction(m_fwm->actionBreakLayout(), am, m_contexts,
508 m_toolActionIds.back(), mformtools);
510 m_toolActionIds.push_back(QLatin1String("FormEditor.LayoutAdjustSize"));
511 const QString adjustShortcut = osMac ? tr("Meta+J") : tr("Ctrl+J");
512 addToolAction(m_fwm->actionAdjustSize(), am, m_contexts,
513 m_toolActionIds.back(), mformtools, adjustShortcut);
515 m_toolActionIds.push_back(QLatin1String("FormEditor.SimplifyLayout"));
516 addToolAction(m_fwm->actionSimplifyLayout(), am, m_contexts,
517 m_toolActionIds.back(), mformtools);
519 createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator1"));
521 addToolAction(m_fwm->actionLower(), am, m_contexts,
522 QLatin1String("FormEditor.Lower"), mformtools);
524 addToolAction(m_fwm->actionRaise(), am, m_contexts,
525 QLatin1String("FormEditor.Raise"), mformtools);
527 // Commands that do not go into the editor toolbar
528 createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator2"));
530 m_actionPreview = m_fwm->actionDefaultPreview();
531 QTC_ASSERT(m_actionPreview, return);
532 addToolAction(m_actionPreview, am, m_contexts,
533 QLatin1String("FormEditor.Preview"), mformtools, tr("Ctrl+Alt+R"));
535 // Preview in style...
536 m_actionGroupPreviewInStyle = m_fwm->actionGroupPreviewInStyle();
537 Core::ActionContainer *previewAC = createPreviewStyleMenu(am, m_actionGroupPreviewInStyle);
538 m_previewInStyleMenu = previewAC->menu();
539 mformtools->addMenu(previewAC);
540 setPreviewMenuEnabled(false);
543 createSeparator(this, am, m_contexts, medit, QLatin1String("FormEditor.Edit.Separator2"), Core::Constants::G_EDIT_OTHER);
545 createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator3"));
546 QAction *actionFormSettings = m_fwm->actionShowFormWindowSettingsDialog();
547 addToolAction(actionFormSettings, am, m_contexts, QLatin1String("FormEditor.FormSettings"), mformtools);
549 createSeparator(this, am, m_contexts, mformtools, QLatin1String("FormEditor.Menu.Tools.Separator4"));
550 m_actionAboutPlugins = new QAction(tr("About Qt Designer plugins...."), this);
551 addToolAction(m_actionAboutPlugins, am, m_contexts,
552 QLatin1String("FormEditor.AboutPlugins"), mformtools);
553 connect(m_actionAboutPlugins, SIGNAL(triggered()), m_fwm, SLOT(aboutPlugins()));
554 m_actionAboutPlugins->setEnabled(false);
557 connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface *)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface *)));
560 QToolBar *FormEditorW::createEditorToolBar() const
562 QToolBar *editorToolBar = new QToolBar;
563 Core::ActionManager *am = m_core->actionManager();
564 const QStringList::const_iterator cend = m_toolActionIds.constEnd();
565 for (QStringList::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
566 Core::Command *cmd = am->command(*it);
567 QTC_ASSERT(cmd, continue);
568 QAction *action = cmd->action();
569 if (!action->icon().isNull()) // Simplify grid has no action yet
570 editorToolBar->addAction(action);
572 const int size = editorToolBar->style()->pixelMetric(QStyle::PM_SmallIconSize);
573 editorToolBar->setIconSize(QSize(size, size));
574 editorToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
575 return editorToolBar;
578 Core::ActionContainer *FormEditorW::createPreviewStyleMenu(Core::ActionManager *am,
579 QActionGroup *actionGroup)
581 const QString menuId = QLatin1String(M_FORMEDITOR_PREVIEW);
582 Core::ActionContainer *menuPreviewStyle = am->createMenu(menuId);
583 menuPreviewStyle->menu()->setTitle(tr("Preview in"));
585 // The preview menu is a list of invisible actions for the embedded design
586 // device profiles (integer data) followed by a separator and the styles
587 // (string data). Make device profiles update their text and hide them
588 // in the configuration dialog.
589 const QList<QAction*> actions = actionGroup->actions();
591 const QString deviceProfilePrefix = QLatin1String("DeviceProfile");
592 const QChar dot = QLatin1Char('.');
594 foreach (QAction* a, actions) {
595 QString name = menuId;
597 const QVariant data = a->data();
598 const bool isDeviceProfile = data.type() == QVariant::Int;
599 if (isDeviceProfile) {
600 name += deviceProfilePrefix;
603 name += data.toString();
604 Core::Command *command = am->registerAction(a, name, m_contexts);
605 bindShortcut(command, a);
606 if (isDeviceProfile) {
607 command->setAttribute(Core::Command::CA_UpdateText);
608 command->setAttribute(Core::Command::CA_NonConfigureable);
610 menuPreviewStyle->addAction(command);
612 return menuPreviewStyle;
615 void FormEditorW::setPreviewMenuEnabled(bool e)
617 m_actionPreview->setEnabled(e);
618 m_previewInStyleMenu->setEnabled(e);
621 void FormEditorW::saveSettings(QSettings *s)
623 s->beginGroup(settingsGroup);
624 m_editorWidget->saveSettings(s);
628 void FormEditorW::critical(const QString &errorMessage)
630 QMessageBox::critical(m_core->mainWindow(), tr("Designer"), errorMessage);
633 // Apply the command shortcut to the action and connects to the command's keySequenceChanged signal
634 void FormEditorW::bindShortcut(Core::Command *command, QAction *action)
636 m_commandToDesignerAction.insert(command, action);
637 connect(command, SIGNAL(keySequenceChanged()),
638 m_shortcutMapper, SLOT(map()));
639 m_shortcutMapper->setMapping(command, command);
640 updateShortcut(command);
643 // Create an action to activate a designer tool
644 QAction *FormEditorW::createEditModeAction(QActionGroup *ag,
645 const QList<int> &context,
646 Core::ActionManager *am,
647 Core::ActionContainer *medit,
648 const QString &actionName,
651 const QString &iconName,
652 const QString &keySequence)
654 QAction *rc = new QAction(actionName, ag);
655 rc->setCheckable(true);
656 if (!iconName.isEmpty())
657 rc->setIcon(designerIcon(iconName));
658 Core::Command *command = am->registerAction(rc, name, context);
659 command->setAttribute(Core::Command::CA_Hide);
660 if (!keySequence.isEmpty())
661 command->setDefaultKeySequence(QKeySequence(keySequence));
662 bindShortcut(command, rc);
663 medit->addAction(command, Core::Constants::G_EDIT_OTHER);
664 rc->setData(toolNumber);
669 // Create a tool action
670 Core::Command *FormEditorW::addToolAction(QAction *a, Core::ActionManager *am,
671 const QList<int> &context, const QString &name,
672 Core::ActionContainer *c1, const QString &keySequence)
674 Core::Command *command = am->registerAction(a, name, context);
675 if (!keySequence.isEmpty())
676 command->setDefaultKeySequence(QKeySequence(keySequence));
677 if (!a->isSeparator())
678 bindShortcut(command, a);
679 c1->addAction(command);
683 EditorData FormEditorW::createEditor(QWidget *parent)
685 if (Designer::Constants::Internal::debug)
686 qDebug() << "FormEditorW::createEditor";
687 // Create and associate form and text editor.
689 m_fwm->closeAllPreviews();
690 qdesigner_internal::FormWindowBase *form = qobject_cast<qdesigner_internal::FormWindowBase *>(m_fwm->createFormWindow(0));
691 QTC_ASSERT(form, return data);
692 connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int)));
693 ResourceHandler *resourceHandler = new ResourceHandler(form);
694 form->setDesignerGrid(qdesigner_internal::FormWindowBase::defaultDesignerGrid());
695 qdesigner_internal::FormWindowBase::setupDefaultAction(form);
696 data.widgetHost = new SharedTools::WidgetHost( /* parent */ 0, form);
697 DesignerXmlEditor *xmlEditor = new DesignerXmlEditor(form, parent);
698 TextEditor::TextEditorSettings::instance()->initializeEditor(xmlEditor);
699 data.formWindowEditor = xmlEditor->designerEditor();
700 connect(data.widgetHost, SIGNAL(formWindowSizeChanged(int,int)),
701 xmlEditor, SIGNAL(changed()));
702 connect(data.formWindowEditor->file(), SIGNAL(changed()),
703 resourceHandler, SLOT(updateResources()));
704 m_editorWidget->add(data);
706 m_toolBar->addEditor(xmlEditor->editableInterface());
711 void FormEditorW::updateShortcut(QObject *command)
713 Core::Command *c = qobject_cast<Core::Command *>(command);
716 QAction *a = m_commandToDesignerAction.value(c);
719 a->setShortcut(c->action()->shortcut());
722 void FormEditorW::currentEditorChanged(Core::IEditor *editor)
724 if (Designer::Constants::Internal::debug)
725 qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
727 if (editor && editor->id() == QLatin1String(Constants::K_DESIGNER_XML_EDITOR_ID)) {
728 FormWindowEditor *xmlEditor = qobject_cast<FormWindowEditor *>(editor);
729 QTC_ASSERT(xmlEditor, return);
730 ensureInitStage(FullyInitialized);
731 SharedTools::WidgetHost *fw = m_editorWidget->formWindowEditorForXmlEditor(xmlEditor);
732 QTC_ASSERT(fw, return)
733 m_editorWidget->setVisibleEditor(xmlEditor);
734 m_fwm->setActiveFormWindow(fw->formWindow());
738 void FormEditorW::activeFormWindowChanged(QDesignerFormWindowInterface *afw)
740 if (Designer::Constants::Internal::debug)
741 qDebug() << Q_FUNC_INFO << afw << " of " << m_fwm->formWindowCount();
743 m_fwm->closeAllPreviews();
744 setPreviewMenuEnabled(afw != 0);
747 EditorData FormEditorW::activeEditor() const
750 return m_editorWidget->activeEditor();
754 void FormEditorW::activateEditMode(int id)
756 if (const int count = m_fwm->formWindowCount())
757 for (int i = 0; i < count; i++)
758 m_fwm->formWindow(i)->setCurrentTool(id);
761 void FormEditorW::activateEditMode(QAction* a)
763 activateEditMode(a->data().toInt());
766 void FormEditorW::toolChanged(int t)
768 typedef QList<QAction *> ActionList;
769 if (const QAction *currentAction = m_actionGroupEditMode->checkedAction())
770 if (currentAction->data().toInt() == t)
772 const ActionList actions = m_actionGroupEditMode->actions();
773 const ActionList::const_iterator cend = actions.constEnd();
774 for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
775 if ( (*it)->data().toInt() == t) {
776 (*it)->setChecked(true);
781 void FormEditorW::closeFormEditorsForXmlEditors(QList<Core::IEditor*> editors)
783 foreach(Core::IEditor *editor, editors) {
784 m_editorWidget->removeFormWindowEditor(editor);
788 void FormEditorW::print()
790 // Printing code courtesy of designer_actions.cpp
791 QDesignerFormWindowInterface *fw = m_fwm->activeFormWindow();
795 const bool oldFullPage = m_core->printer()->fullPage();
796 const QPrinter::Orientation oldOrientation = m_core->printer()->orientation ();
797 m_core->printer()->setFullPage(false);
800 // Grab the image to be able to a suggest suitable orientation
801 QString errorMessage;
802 const QPixmap pixmap = m_fwm->createPreviewPixmap(&errorMessage);
803 if (pixmap.isNull()) {
804 critical(tr("The image could not be created: %1").arg(errorMessage));
808 const QSizeF pixmapSize = pixmap.size();
809 m_core->printer()->setOrientation( pixmapSize.width() > pixmapSize.height() ? QPrinter::Landscape : QPrinter::Portrait);
811 // Printer parameters
812 QPrintDialog dialog(m_core->printer(), fw);
816 const QCursor oldCursor = m_core->mainWindow()->cursor();
817 m_core->mainWindow()->setCursor(Qt::WaitCursor);
818 // Estimate of required scaling to make form look the same on screen and printer.
819 const double suggestedScaling = static_cast<double>(m_core->printer()->physicalDpiX()) / static_cast<double>(fw->physicalDpiX());
821 QPainter painter(m_core->printer());
822 painter.setRenderHint(QPainter::SmoothPixmapTransform);
825 const QRectF page = painter.viewport();
826 const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
827 const double scaling = qMin(suggestedScaling, maxScaling);
829 const double xOffset = page.left() + qMax(0.0, (page.size().width() - scaling * pixmapSize.width()) / 2.0);
830 const double yOffset = page.top() + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
833 painter.translate(xOffset, yOffset);
834 painter.scale(scaling, scaling);
835 painter.drawPixmap(0, 0, pixmap);
836 m_core->mainWindow()->setCursor(oldCursor);
839 m_core->printer()->setFullPage(oldFullPage);
840 m_core->printer()->setOrientation(oldOrientation);
843 } // namespace Internal
844 } // namespace Designer