formeditorw.cpp 31.7 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

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

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

55 56 57
#include <QDesignerFormEditorPluginInterface>
#include <QDesignerFormEditorInterface>
#include <QDesignerComponents>
con's avatar
con committed
58

59
#if QT_VERSION >= 0x050000
60
#    include <QDesignerFormWindowManagerInterface>
61 62 63 64 65 66 67
#else
#    include "qt_private/pluginmanager_p.h"
#    include "qt_private/iconloader_p.h"  // createIconSet
#    include "qt_private/qdesigner_formwindowmanager_p.h"
#    include "qt_private/formwindowbase_p.h"
#endif

68 69 70 71
#include <QDesignerWidgetBoxInterface>
#include <abstractobjectinspector.h>
#include <QDesignerPropertyEditorInterface>
#include <QDesignerActionEditorInterface>
con's avatar
con committed
72

73 74 75 76 77 78 79 80 81 82 83 84 85
#include <QAction>
#include <QActionGroup>
#include <QApplication>
#include <QCursor>
#include <QDockWidget>
#include <QMessageBox>
#include <QKeySequence>
#include <QPrintDialog>
#include <QPrinter>
#include <QPainter>
#include <QStyle>
#include <QToolBar>
#include <QVBoxLayout>
con's avatar
con committed
86

87 88 89 90 91
#include <QDebug>
#include <QSettings>
#include <QSignalMapper>
#include <QPluginLoader>
#include <QTime>
con's avatar
con committed
92

93
static const char settingsGroupC[] = "Designer";
con's avatar
con committed
94

95 96
/* Actions of the designer plugin:
 * Designer provides a toolbar which is subject to a context change (to
Tobias Hunger's avatar
Tobias Hunger committed
97
 * "edit mode" context) when it is focused.
98 99 100 101 102
 * In order to prevent its actions from being disabled/hidden by that context
 * change, the actions are registered on the global context. In currentEditorChanged(),
 * the ones that are present in the global edit menu are set visible/invisible manually.
 * The designer context is currently used for Cut/Copy/Paste, etc. */

con's avatar
con committed
103 104
static inline QIcon designerIcon(const QString &iconName)
{
105 106 107
#if QT_VERSION >= 0x050000
    const QIcon icon = QDesignerFormEditorInterface::createIcon(iconName);
#else
con's avatar
con committed
108
    const QIcon icon = qdesigner_internal::createIconSet(iconName);
109
#endif
con's avatar
con committed
110 111 112 113 114
    if (icon.isNull())
        qWarning() << "Unable to locate " << iconName;
    return icon;
}

hjk's avatar
hjk committed
115
using namespace Core;
con's avatar
con committed
116 117
using namespace Designer::Constants;

118 119
namespace Designer {
namespace Internal {
con's avatar
con committed
120 121 122

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

con's avatar
con committed
123 124 125 126 127 128 129 130
FormEditorW *FormEditorW::m_self = 0;

FormEditorW::FormEditorW() :
    m_formeditor(QDesignerComponents::createFormEditor(0)),
    m_integration(0),
    m_fwm(0),
    m_initStage(RegisterPlugins),
    m_actionGroupEditMode(0),
131 132 133
    m_actionPrint(0),
    m_actionPreview(0),
    m_actionGroupPreviewInStyle(0),
134
    m_previewInStyleMenu(0),
135
    m_actionAboutPlugins(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
136 137
    m_shortcutMapper(new QSignalMapper(this)),
    m_context(0),
138 139
    m_modeWidget(0),
    m_editorWidget(0),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
140 141 142
    m_designMode(0),
    m_editorToolBar(0),
    m_toolBar(0)
con's avatar
con committed
143
{
144
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
145
        qDebug() << Q_FUNC_INFO;
hjk's avatar
hjk committed
146
    QTC_ASSERT(!m_self, return);
con's avatar
con committed
147 148 149 150 151
    m_self = this;

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

hjk's avatar
hjk committed
152
    m_formeditor->setTopLevel(ICore::mainWindow());
con's avatar
con committed
153 154
    m_formeditor->setSettingsManager(new SettingsManager());

155 156 157
#if QT_VERSION >= 0x050000
    m_fwm = m_formeditor->formWindowManager();
#else
con's avatar
con committed
158
    m_fwm = qobject_cast<qdesigner_internal::QDesignerFormWindowManager*>(m_formeditor->formWindowManager());
159
#endif
hjk's avatar
hjk committed
160
    QTC_ASSERT(m_fwm, return);
con's avatar
con committed
161

162
    m_contexts.add(Designer::Constants::C_FORMEDITOR);
163

con's avatar
con committed
164 165 166 167 168 169 170
    setupActions();

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

hjk's avatar
hjk committed
171
    connect(EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
Robert Loehning's avatar
Robert Loehning committed
172 173 174
            this, SLOT(currentEditorChanged(Core::IEditor*)));
    connect(m_shortcutMapper, SIGNAL(mapped(QObject*)),
            this, SLOT(updateShortcut(QObject*)));
con's avatar
con committed
175 176 177 178
}

FormEditorW::~FormEditorW()
{
179
    if (m_context)
hjk's avatar
hjk committed
180
        ICore::removeContextObject(m_context);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
181
    if (m_initStage == FullyInitialized) {
hjk's avatar
hjk committed
182
        QSettings *s = ICore::settings();
183 184 185
        s->beginGroup(QLatin1String(settingsGroupC));
        m_editorWidget->saveSettings(s);
        s->endGroup();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
186

187 188 189 190
        m_designMode->unregisterDesignWidget(m_modeWidget);
        delete m_modeWidget;
        m_modeWidget = 0;
    }
con's avatar
con committed
191 192

    delete m_formeditor;
193 194
    qDeleteAll(m_settingsPages);
    m_settingsPages.clear();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
195 196
    delete m_integration;

197 198 199
    m_self = 0;
}

200
// Add an actioon to toggle the view state of a dock window
hjk's avatar
hjk committed
201 202
void FormEditorW::addDockViewAction(ActionContainer *viewMenu,
                                    int index, const Context &context,
203
                                    const QString &title, Id id)
204 205 206 207
{
    if (const QDockWidget *dw = m_editorWidget->designerDockWidgets()[index]) {
        QAction *action = dw->toggleViewAction();
        action->setText(title);
hjk's avatar
hjk committed
208 209
        Command *cmd = addToolAction(action, context, id, viewMenu, QString());
        cmd->setAttribute(Command::CA_Hide);
210 211 212 213 214 215
    }
}

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

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

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

Eike Ziller's avatar
Eike Ziller committed
225
    addDockViewAction(viewMenu, PropertyEditorSubWindow, m_contexts,
hjk's avatar
hjk committed
226
                      tr("Property Editor"), "FormEditor.PropertyEditor");
227

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

Eike Ziller's avatar
Eike Ziller committed
231
    addDockViewAction(viewMenu, ActionEditorSubWindow, m_contexts,
hjk's avatar
hjk committed
232
                      tr("Action Editor"), "FormEditor.ActionEditor");
233 234
    // Reset
    Command *cmd = addToolAction(m_editorWidget->menuSeparator(), m_contexts, "FormEditor.SeparatorReset", viewMenu);
hjk's avatar
hjk committed
235
    cmd->setAttribute(Command::CA_Hide);
236

hjk's avatar
hjk committed
237
    cmd = addToolAction(m_editorWidget->resetLayoutAction(), m_contexts, "FormEditor.ResetToDefaultLayout", viewMenu);
238
    connect(m_editorWidget, SIGNAL(resetLayout()), m_editorWidget, SLOT(resetToDefaultLayout()));
hjk's avatar
hjk committed
239
    cmd->setAttribute(Command::CA_Hide);
con's avatar
con committed
240 241 242 243
}

void FormEditorW::fullInit()
{
hjk's avatar
hjk committed
244
    QTC_ASSERT(m_initStage == RegisterPlugins, return);
con's avatar
con committed
245
    QTime *initTime = 0;
246
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
247 248 249 250 251 252 253 254
        initTime = new QTime;
        initTime->start();
    }

    QDesignerComponents::createTaskMenu(m_formeditor, parent());
    QDesignerComponents::initializePlugins(designerEditor());
    QDesignerComponents::initializeResources();
    initDesignerSubWindows();
255
    m_integration = new QtCreatorIntegration(m_formeditor, this);
con's avatar
con committed
256
    m_formeditor->setIntegration(m_integration);
257
    // Connect Qt Designer help request to HelpManager.
kh1's avatar
kh1 committed
258
    connect(m_integration, SIGNAL(creatorHelpRequested(QUrl)),
259
        HelpManager::instance(), SLOT(handleHelpRequest(QUrl)));
con's avatar
con committed
260 261 262 263 264

    /**
     * This will initialize our TabOrder, Signals and slots and Buddy editors.
     */
    QList<QObject*> plugins = QPluginLoader::staticInstances();
265 266 267
#if QT_VERSION >= 0x050000
    plugins += m_formeditor->pluginInstances();
#else
con's avatar
con committed
268
    plugins += m_formeditor->pluginManager()->instances();
269
#endif
con's avatar
con committed
270 271 272 273 274 275 276
    foreach (QObject *plugin, plugins) {
        if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
            if (!formEditorPlugin->isInitialized())
                formEditorPlugin->initialize(m_formeditor);
        }
    }

277 278 279
    if (m_actionAboutPlugins)
        m_actionAboutPlugins->setEnabled(true);

280
    if (Designer::Constants::Internal::debug) {
con's avatar
con committed
281 282 283
        qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
        delete initTime;
    }
284

hjk's avatar
hjk committed
285
    connect(EditorManager::instance(), SIGNAL(editorsClosed(QList<Core::IEditor*>)),
Lasse Holmstedt's avatar
Lasse Holmstedt committed
286
            SLOT(closeFormEditorsForXmlEditors(QList<Core::IEditor*>)));
287 288
    // Nest toolbar and editor widget
    m_editorWidget = new EditorWidget(this);
hjk's avatar
hjk committed
289
    QSettings *settings = ICore::settings();
290
    settings->beginGroup(QLatin1String(settingsGroupC));
291 292
    m_editorWidget->restoreSettings(settings);
    settings->endGroup();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
293

Lasse Holmstedt's avatar
Lasse Holmstedt committed
294
    m_editorToolBar = createEditorToolBar();
295
    m_toolBar = new EditorToolBar;
hjk's avatar
hjk committed
296
    m_toolBar->setToolbarCreationFlags(EditorToolBar::FlagsStandalone);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
297 298 299
    m_toolBar->setNavigationVisible(false);
    m_toolBar->addCenterToolBar(m_editorToolBar);

hjk's avatar
hjk committed
300
    m_designMode = DesignMode::instance();
301 302 303 304 305
    m_modeWidget = new QWidget;
    m_modeWidget->setObjectName(QLatin1String("DesignerModeWidget"));
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setMargin(0);
    layout->setSpacing(0);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
306
    layout->addWidget(m_toolBar);
307 308
    // Avoid mode switch to 'Edit' mode when the application started by
    // 'Run' in 'Design' mode emits output.
hjk's avatar
hjk committed
309
    MiniSplitter *splitter = new MiniSplitter(Qt::Vertical);
310
    splitter->addWidget(m_editorWidget);
hjk's avatar
hjk committed
311
    QWidget *outputPane = new OutputPanePlaceHolder(m_designMode, splitter);
312 313
    outputPane->setObjectName(QLatin1String("DesignerOutputPanePlaceHolder"));
    splitter->addWidget(outputPane);
314
    layout->addWidget(splitter);
315 316
    m_modeWidget->setLayout(layout);

hjk's avatar
hjk committed
317
    Context designerContexts = m_contexts;
318
    designerContexts.add(Core::Constants::C_EDITORMANAGER);
319
    m_context = new DesignerContext(designerContexts, m_modeWidget, this);
hjk's avatar
hjk committed
320
    ICore::addContextObject(m_context);
321

322
    m_designMode->registerDesignWidget(m_modeWidget, QStringList(QLatin1String(FORM_MIMETYPE)), m_contexts);
323 324

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

con's avatar
con committed
326 327 328 329 330 331 332 333
    m_initStage = FullyInitialized;
}

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

    QDesignerWidgetBoxInterface *wb = QDesignerComponents::createWidgetBox(m_formeditor, 0);
con's avatar
con committed
334
    wb->setWindowTitle(tr("Widget Box"));
335
    wb->setObjectName(QLatin1String("WidgetBox"));
con's avatar
con committed
336 337 338 339
    m_formeditor->setWidgetBox(wb);
    m_designerSubWindows[WidgetBoxSubWindow] = wb;

    QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, 0);
con's avatar
con committed
340
    oi->setWindowTitle(tr("Object Inspector"));
341
    oi->setObjectName(QLatin1String("ObjectInspector"));
con's avatar
con committed
342 343 344 345
    m_formeditor->setObjectInspector(oi);
    m_designerSubWindows[ObjectInspectorSubWindow] = oi;

    QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, 0);
con's avatar
con committed
346
    pe->setWindowTitle(tr("Property Editor"));
347
    pe->setObjectName(QLatin1String("PropertyEditor"));
con's avatar
con committed
348 349 350 351
    m_formeditor->setPropertyEditor(pe);
    m_designerSubWindows[PropertyEditorSubWindow] = pe;

    QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, 0);
Daniel Molkentin's avatar
Daniel Molkentin committed
352
    se->setWindowTitle(tr("Signals && Slots Editor"));
353
    se->setObjectName(QLatin1String("SignalsAndSlotsEditor"));
con's avatar
con committed
354 355 356
    m_designerSubWindows[SignalSlotEditorSubWindow] = se;

    QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, 0);
con's avatar
con committed
357
    ae->setWindowTitle(tr("Action Editor"));
358
    ae->setObjectName(QLatin1String("ActionEditor"));
con's avatar
con committed
359 360 361 362
    m_formeditor->setActionEditor(ae);
    m_designerSubWindows[ActionEditorSubWindow] = ae;
}

363 364 365 366 367
QList<Core::IOptionsPage *> FormEditorW::optionsPages() const
{
    return m_settingsPages;
}

con's avatar
con committed
368 369
void FormEditorW::ensureInitStage(InitializationStage s)
{
370
    if (Designer::Constants::Internal::debug)
con's avatar
con committed
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
        qDebug() << Q_FUNC_INFO << s;
    if (!m_self)
        m_self = new FormEditorW;
    if (m_self->m_initStage >= s)
        return;
    QApplication::setOverrideCursor(Qt::WaitCursor);
    m_self->fullInit();
    QApplication::restoreOverrideCursor();
}

FormEditorW *FormEditorW::instance()
{
    ensureInitStage(FullyInitialized);
    return m_self;
}

void FormEditorW::deleteInstance()
{
    delete m_self;
}

void FormEditorW::setupActions()
{
    //menus
hjk's avatar
hjk committed
395
    ActionContainer *medit = ActionManager::actionContainer(Core::Constants::M_EDIT);
396
    ActionContainer *mformtools = ActionManager::actionContainer(M_FORMEDITOR);
con's avatar
con committed
397 398

    //overridden actions
hjk's avatar
hjk committed
399 400 401 402 403 404
    bindShortcut(ActionManager::registerAction(m_fwm->actionUndo(), Core::Constants::UNDO, m_contexts), m_fwm->actionUndo());
    bindShortcut(ActionManager::registerAction(m_fwm->actionRedo(), Core::Constants::REDO, m_contexts), m_fwm->actionRedo());
    bindShortcut(ActionManager::registerAction(m_fwm->actionCut(), Core::Constants::CUT, m_contexts), m_fwm->actionCut());
    bindShortcut(ActionManager::registerAction(m_fwm->actionCopy(), Core::Constants::COPY, m_contexts), m_fwm->actionCopy());
    bindShortcut(ActionManager::registerAction(m_fwm->actionPaste(), Core::Constants::PASTE, m_contexts), m_fwm->actionPaste());
    bindShortcut(ActionManager::registerAction(m_fwm->actionSelectAll(), Core::Constants::SELECTALL, m_contexts), m_fwm->actionSelectAll());
con's avatar
con committed
405 406

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

410 411 412
    //'delete' action. Do not set a shortcut as Designer handles
    // the 'Delete' key by event filter. Setting a shortcut triggers
    // buggy behaviour on Mac (Pressing Delete in QLineEdit removing the widget).
hjk's avatar
hjk committed
413
    Command *command;
414
    command = ActionManager::registerAction(m_fwm->actionDelete(), "FormEditor.Edit.Delete", m_contexts);
415
    bindShortcut(command, m_fwm->actionDelete());
hjk's avatar
hjk committed
416
    command->setAttribute(Command::CA_Hide);
con's avatar
con committed
417 418 419 420 421 422
    medit->addAction(command, Core::Constants::G_EDIT_COPYPASTE);

    m_actionGroupEditMode = new QActionGroup(this);
    m_actionGroupEditMode->setExclusive(true);
    connect(m_actionGroupEditMode, SIGNAL(triggered(QAction*)), this, SLOT(activateEditMode(QAction*)));

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

425
    m_toolActionIds.push_back("FormEditor.WidgetEditor");
Eike Ziller's avatar
Eike Ziller committed
426
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
427
                         tr("Edit Widgets"), m_toolActionIds.back(),
con's avatar
con committed
428 429
                         EditModeWidgetEditor, QLatin1String("widgettool.png"), tr("F3"));

430
    m_toolActionIds.push_back("FormEditor.SignalsSlotsEditor");
Eike Ziller's avatar
Eike Ziller committed
431
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
432
                         tr("Edit Signals/Slots"), m_toolActionIds.back(),
con's avatar
con committed
433 434
                         EditModeSignalsSlotEditor, QLatin1String("signalslottool.png"), tr("F4"));

435
    m_toolActionIds.push_back("FormEditor.BuddyEditor");
Eike Ziller's avatar
Eike Ziller committed
436
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
437
                         tr("Edit Buddies"), m_toolActionIds.back(),
con's avatar
con committed
438 439
                         EditModeBuddyEditor, QLatin1String("buddytool.png"));

440
    m_toolActionIds.push_back("FormEditor.TabOrderEditor");
Eike Ziller's avatar
Eike Ziller committed
441
    createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
442
                         tr("Edit Tab Order"),  m_toolActionIds.back(),
con's avatar
con committed
443 444 445
                         EditModeTabOrderEditor, QLatin1String("tabordertool.png"));

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

451
    m_toolActionIds.push_back("FormEditor.LayoutVertically");
hjk's avatar
hjk committed
452
    const QString vertLayoutShortcut = UseMacShortcuts ? tr("Meta+L") : tr("Ctrl+L");
Eike Ziller's avatar
Eike Ziller committed
453
    addToolAction(m_fwm->actionVerticalLayout(), m_contexts,
454
                  m_toolActionIds.back(),  mformtools, vertLayoutShortcut);
con's avatar
con committed
455

456
    m_toolActionIds.push_back("FormEditor.SplitHorizontal");
Eike Ziller's avatar
Eike Ziller committed
457
    addToolAction(m_fwm->actionSplitHorizontal(), m_contexts,
con's avatar
con committed
458 459
                  m_toolActionIds.back(), mformtools);

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

464
    m_toolActionIds.push_back("FormEditor.LayoutForm");
Eike Ziller's avatar
Eike Ziller committed
465
    addToolAction(m_fwm->actionFormLayout(), m_contexts,
con's avatar
con committed
466 467
                  m_toolActionIds.back(),  mformtools);

468
    m_toolActionIds.push_back("FormEditor.LayoutGrid");
hjk's avatar
hjk committed
469
    const QString gridShortcut = UseMacShortcuts ? tr("Meta+Shift+G") : tr("Ctrl+G");
Eike Ziller's avatar
Eike Ziller committed
470
    addToolAction(m_fwm->actionGridLayout(), m_contexts,
471
                  m_toolActionIds.back(),  mformtools, gridShortcut);
con's avatar
con committed
472

473
    m_toolActionIds.push_back("FormEditor.LayoutBreak");
Eike Ziller's avatar
Eike Ziller committed
474
    addToolAction(m_fwm->actionBreakLayout(), m_contexts,
con's avatar
con committed
475 476
                  m_toolActionIds.back(), mformtools);

477
    m_toolActionIds.push_back("FormEditor.LayoutAdjustSize");
hjk's avatar
hjk committed
478
    const QString adjustShortcut = UseMacShortcuts ? tr("Meta+J") : tr("Ctrl+J");
Eike Ziller's avatar
Eike Ziller committed
479
    addToolAction(m_fwm->actionAdjustSize(), m_contexts,
480
                  m_toolActionIds.back(),  mformtools, adjustShortcut);
con's avatar
con committed
481

482
    m_toolActionIds.push_back("FormEditor.SimplifyLayout");
Eike Ziller's avatar
Eike Ziller committed
483
    addToolAction(m_fwm->actionSimplifyLayout(), m_contexts,
con's avatar
con committed
484 485
                  m_toolActionIds.back(),  mformtools);

486
    mformtools->addSeparator(m_contexts);
con's avatar
con committed
487

488 489
    addToolAction(m_fwm->actionLower(), m_contexts, "FormEditor.Lower", mformtools);
    addToolAction(m_fwm->actionRaise(), m_contexts, "FormEditor.Raise", mformtools);
con's avatar
con committed
490 491

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

494 495 496
#if QT_VERSION >= 0x050000
    m_actionPreview = m_fwm->action(QDesignerFormWindowManagerInterface::DefaultPreviewAction);
#else
con's avatar
con committed
497
    m_actionPreview = m_fwm->actionDefaultPreview();
498
#endif
hjk's avatar
hjk committed
499
    QTC_ASSERT(m_actionPreview, return);
500
    addToolAction(m_actionPreview, m_contexts, "FormEditor.Preview", mformtools, tr("Alt+Shift+R"));
con's avatar
con committed
501 502

    // Preview in style...
503 504 505
#if QT_VERSION >= 0x050000
    m_actionGroupPreviewInStyle = m_fwm->actionGroup(QDesignerFormWindowManagerInterface::StyledPreviewActionGroup);
#else
con's avatar
con committed
506
    m_actionGroupPreviewInStyle = m_fwm->actionGroupPreviewInStyle();
507 508
#endif

hjk's avatar
hjk committed
509
    ActionContainer *previewAC = createPreviewStyleMenu(m_actionGroupPreviewInStyle);
510 511 512
    m_previewInStyleMenu = previewAC->menu();
    mformtools->addMenu(previewAC);
    setPreviewMenuEnabled(false);
con's avatar
con committed
513 514

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

517
    mformtools->addSeparator(m_contexts);
518

519
    mformtools->addSeparator(m_contexts, Core::Constants::G_DEFAULT_THREE);
520 521 522
#if QT_VERSION >= 0x050000
    QAction *actionFormSettings = m_fwm->action(QDesignerFormWindowManagerInterface::FormWindowSettingsDialogAction);
#else
con's avatar
con committed
523
    QAction *actionFormSettings = m_fwm->actionShowFormWindowSettingsDialog();
524
#endif
525 526
    addToolAction(actionFormSettings, m_contexts, "FormEditor.FormSettings", mformtools,
                  QString(), Core::Constants::G_DEFAULT_THREE);
527

528
    mformtools->addSeparator(m_contexts, Core::Constants::G_DEFAULT_THREE);
529
    m_actionAboutPlugins = new QAction(tr("About Qt Designer Plugins..."), this);
530
    m_actionAboutPlugins->setMenuRole(QAction::NoRole);
531 532
    addToolAction(m_actionAboutPlugins, m_contexts, "FormEditor.AboutPlugins", mformtools,
                  QString(), Core::Constants::G_DEFAULT_THREE);
533 534 535 536 537 538 539
    connect(m_actionAboutPlugins,  SIGNAL(triggered()), m_fwm,
#if QT_VERSION >= 0x050000
            SLOT(showPluginDialog())
#else
            SLOT(aboutPlugins())
#endif
            );
540 541
    m_actionAboutPlugins->setEnabled(false);

con's avatar
con committed
542
    // FWM
Robert Loehning's avatar
Robert Loehning committed
543
    connect(m_fwm, SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)), this, SLOT(activeFormWindowChanged(QDesignerFormWindowInterface*)));
con's avatar
con committed
544 545 546 547
}

QToolBar *FormEditorW::createEditorToolBar() const
{
548
    QToolBar *editorToolBar = new QToolBar;
hjk's avatar
hjk committed
549 550 551
    const QList<Id>::const_iterator cend = m_toolActionIds.constEnd();
    for (QList<Id>::const_iterator it = m_toolActionIds.constBegin(); it != cend; ++it) {
        Command *cmd = ActionManager::command(*it);
hjk's avatar
hjk committed
552
        QTC_ASSERT(cmd, continue);
con's avatar
con committed
553 554
        QAction *action = cmd->action();
        if (!action->icon().isNull()) // Simplify grid has no action yet
555
            editorToolBar->addAction(action);
con's avatar
con committed
556
    }
557 558 559 560
    const int size = editorToolBar->style()->pixelMetric(QStyle::PM_SmallIconSize);
    editorToolBar->setIconSize(QSize(size, size));
    editorToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    return editorToolBar;
con's avatar
con committed
561 562
}

hjk's avatar
hjk committed
563
ActionContainer *FormEditorW::createPreviewStyleMenu(QActionGroup *actionGroup)
con's avatar
con committed
564 565
{
    const QString menuId = QLatin1String(M_FORMEDITOR_PREVIEW);
hjk's avatar
hjk committed
566
    ActionContainer *menuPreviewStyle = ActionManager::createMenu(M_FORMEDITOR_PREVIEW);
con's avatar
con committed
567 568 569 570 571 572 573 574 575 576 577
    menuPreviewStyle->menu()->setTitle(tr("Preview in"));

    // The preview menu is a list of invisible actions for the embedded design
    // device profiles (integer data) followed by a separator and the styles
    // (string data). Make device profiles update their text and hide them
    // in the configuration dialog.
    const QList<QAction*> actions = actionGroup->actions();

    const QString deviceProfilePrefix = QLatin1String("DeviceProfile");
    const QChar dot = QLatin1Char('.');

hjk's avatar
hjk committed
578
    foreach (QAction* a, actions) {
con's avatar
con committed
579 580 581 582 583 584 585 586 587
        QString name = menuId;
        name += dot;
        const QVariant data = a->data();
        const bool isDeviceProfile = data.type() == QVariant::Int;
        if (isDeviceProfile) {
            name += deviceProfilePrefix;
            name += dot;
        }
        name += data.toString();
hjk's avatar
hjk committed
588
        Command *command = ActionManager::registerAction(a, Id::fromString(name), m_contexts);
589
        bindShortcut(command, a);
con's avatar
con committed
590
        if (isDeviceProfile) {
hjk's avatar
hjk committed
591 592
            command->setAttribute(Command::CA_UpdateText);
            command->setAttribute(Command::CA_NonConfigurable);
con's avatar
con committed
593 594 595 596 597 598
        }
        menuPreviewStyle->addAction(command);
    }
    return menuPreviewStyle;
}

599 600 601 602 603 604
void FormEditorW::setPreviewMenuEnabled(bool e)
{
    m_actionPreview->setEnabled(e);
    m_previewInStyleMenu->setEnabled(e);
}

con's avatar
con committed
605 606
void FormEditorW::saveSettings(QSettings *s)
{
607
    s->beginGroup(QLatin1String(settingsGroupC));
608
    m_editorWidget->saveSettings(s);
609
    s->endGroup();
con's avatar
con committed
610 611 612 613
}

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

617
// Apply the command shortcut to the action and connects to the command's keySequenceChanged signal
hjk's avatar
hjk committed
618
void FormEditorW::bindShortcut(Command *command, QAction *action)
619 620 621 622 623 624 625 626 627 628
{
    m_commandToDesignerAction.insert(command, action);
    connect(command, SIGNAL(keySequenceChanged()),
            m_shortcutMapper, SLOT(map()));
    m_shortcutMapper->setMapping(command, command);
    updateShortcut(command);
}

// Create an action to activate a designer tool
QAction *FormEditorW::createEditModeAction(QActionGroup *ag,
hjk's avatar
hjk committed
629 630
                                     const Context &context,
                                     ActionContainer *medit,
631
                                     const QString &actionName,
632
                                     Id id,
633 634 635 636 637 638 639 640
                                     int toolNumber,
                                     const QString &iconName,
                                     const QString &keySequence)
{
    QAction *rc = new QAction(actionName, ag);
    rc->setCheckable(true);
    if (!iconName.isEmpty())
         rc->setIcon(designerIcon(iconName));
hjk's avatar
hjk committed
641
    Command *command = ActionManager::registerAction(rc, id, context);
642
    command->setAttribute(Core::Command::CA_Hide);
643 644 645 646 647 648 649 650 651 652
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
    bindShortcut(command, rc);
    medit->addAction(command, Core::Constants::G_EDIT_OTHER);
    rc->setData(toolNumber);
    ag->addAction(rc);
    return rc;
}

// Create a tool action
653
Command *FormEditorW::addToolAction(QAction *a, const Context &context, Id id,
654 655
                                          ActionContainer *c1, const QString &keySequence,
                                    Core::Id groupId)
656
{
hjk's avatar
hjk committed
657
    Command *command = ActionManager::registerAction(a, id, context);
658 659
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
660 661
    if (!a->isSeparator())
        bindShortcut(command, a);
662
    c1->addAction(command, groupId);
663
    return command;
664 665
}

666
EditorData FormEditorW::createEditor()
con's avatar
con committed
667
{
668 669 670 671
    if (Designer::Constants::Internal::debug)
        qDebug() << "FormEditorW::createEditor";
    // Create and associate form and text editor.
    EditorData data;
con's avatar
con committed
672
    m_fwm->closeAllPreviews();
673 674 675
#if QT_VERSION >= 0x050000
    QDesignerFormWindowInterface *form = m_fwm->createFormWindow(0);
#else
676
    qdesigner_internal::FormWindowBase *form = qobject_cast<qdesigner_internal::FormWindowBase *>(m_fwm->createFormWindow(0));
677
#endif
678
    QTC_ASSERT(form, return data);
con's avatar
con committed
679
    connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int)));
680
    ResourceHandler *resourceHandler = new ResourceHandler(form);
681
#if QT_VERSION < 0x050000
682
    form->setDesignerGrid(qdesigner_internal::FormWindowBase::defaultDesignerGrid());
con's avatar
con committed
683
    qdesigner_internal::FormWindowBase::setupDefaultAction(form);
684
#endif
685
    data.widgetHost = new SharedTools::WidgetHost( /* parent */ 0, form);
686
    DesignerXmlEditorWidget *xmlEditor = new DesignerXmlEditorWidget(form);
687
    TextEditor::TextEditorSettings::initializeEditor(xmlEditor);
688
    data.formWindowEditor = xmlEditor->designerEditor();
689
    connect(data.formWindowEditor->document(), SIGNAL(filePathChanged(QString,QString)),
690
            resourceHandler, SLOT(updateResources()));
691
    m_editorWidget->add(data);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
692

693
    m_toolBar->addEditor(xmlEditor->editor());
Lasse Holmstedt's avatar
Lasse Holmstedt committed
694

695
    return data;
con's avatar
con committed
696 697
}

698 699
void FormEditorW::updateShortcut(QObject *command)
{
hjk's avatar
hjk committed
700
    Command *c = qobject_cast<Command *>(command);
701 702 703 704 705 706 707 708
    if (!c)
        return;
    QAction *a = m_commandToDesignerAction.value(c);
    if (!a)
        return;
    a->setShortcut(c->action()->shortcut());
}

hjk's avatar
hjk committed
709
void FormEditorW::currentEditorChanged(IEditor *editor)
con's avatar
con committed
710
{
711 712
    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
con's avatar
con committed
713

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

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

    m_fwm->closeAllPreviews();
731
    setPreviewMenuEnabled(afw != 0);
con's avatar
con committed
732 733
}

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

void FormEditorW::activateEditMode(int id)
{
    if (const int count = m_fwm->formWindowCount())
        for (int i = 0; i <  count; i++)
             m_fwm->formWindow(i)->setCurrentTool(id);
}

void FormEditorW::activateEditMode(QAction* a)
{
    activateEditMode(a->data().toInt());
}

void FormEditorW::toolChanged(int t)
{
    typedef QList<QAction *> ActionList;
    if (const QAction *currentAction = m_actionGroupEditMode->checkedAction())
        if (currentAction->data().toInt() == t)
            return;
    const ActionList actions = m_actionGroupEditMode->actions();
    const ActionList::const_iterator cend = actions.constEnd();
    for (ActionList::const_iterator it = actions.constBegin(); it != cend; ++it)
        if ( (*it)->data().toInt() == t) {
            (*it)->setChecked(true);
            break;
        }
}

hjk's avatar
hjk committed
768
void FormEditorW::closeFormEditorsForXmlEditors(QList<IEditor*> editors)
Lasse Holmstedt's avatar
Lasse Holmstedt committed
769
{
hjk's avatar
hjk committed
770
    foreach (IEditor *editor, editors)
771
        m_editorWidget->removeFormWindowEditor(editor);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
772 773
}

con's avatar
con committed
774 775 776 777 778 779 780
void FormEditorW::print()
{
    // Printing code courtesy of designer_actions.cpp
    QDesignerFormWindowInterface *fw = m_fwm->activeFormWindow();
    if (!fw)
        return;

hjk's avatar
hjk committed
781
    QPrinter *printer = ICore::printer();
hjk's avatar
hjk committed
782 783 784
    const bool oldFullPage =  printer->fullPage();
    const QPrinter::Orientation oldOrientation =  printer->orientation ();
    printer->setFullPage(false);
con's avatar
con committed
785 786 787
    do {
        // Grab the image to be able to a suggest suitable orientation
        QString errorMessage;
788 789 790
#if QT_VERSION >= 0x050000
        const QPixmap pixmap = m_fwm->createPreviewPixmap();
#else
con's avatar
con committed
791
        const QPixmap pixmap = m_fwm->createPreviewPixmap(&errorMessage);
792
#endif
con's avatar
con committed
793
        if (pixmap.isNull()) {
Jure Repinc's avatar
Jure Repinc committed
794
            critical(tr("The image could not be created: %1").arg(errorMessage));
con's avatar
con committed
795 796 797 798
            break;
        }

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

        // Printer parameters
hjk's avatar
hjk committed
802
        QPrintDialog dialog(printer, fw);
con's avatar
con committed
803 804 805
        if (!dialog.exec())
           break;

hjk's avatar
hjk committed
806
        QWidget *mainWindow = ICore::mainWindow();
hjk's avatar
hjk committed
807 808
        const QCursor oldCursor = mainWindow->cursor();
        mainWindow->setCursor(Qt::WaitCursor);
con's avatar
con committed
809
        // Estimate of required scaling to make form look the same on screen and printer.
hjk's avatar
hjk committed
810
        const double suggestedScaling = static_cast<double>(printer->physicalDpiX()) /  static_cast<double>(fw->physicalDpiX());
con's avatar
con committed
811

hjk's avatar
hjk committed
812
        QPainter painter(printer);
con's avatar
con committed
813 814 815 816 817 818 819
        painter.setRenderHint(QPainter::SmoothPixmapTransform);

        // Clamp to page
        const QRectF page =  painter.viewport();
        const double maxScaling = qMin(page.size().width() / pixmapSize.width(), page.size().height() / pixmapSize.height());
        const double scaling = qMin(suggestedScaling, maxScaling);

Felix Geyer's avatar
Felix Geyer committed
820 821
        const double xOffset = page.left() + qMax(0.0, (page.size().width()  - scaling * pixmapSize.width())  / 2.0);
        const double yOffset = page.top()  + qMax(0.0, (page.size().height() - scaling * pixmapSize.height()) / 2.0);
con's avatar
con committed
822 823 824 825 826

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

    } while (false);
hjk's avatar
hjk committed
830 831
    printer->setFullPage(oldFullPage);
    printer->setOrientation(oldOrientation);
con's avatar
con committed
832
}
Lasse Holmstedt's avatar
Lasse Holmstedt committed
833

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