Files
qt-creator/src/plugins/designer/formeditorw.cpp

880 lines
33 KiB
C++
Raw Normal View History

// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
2008-12-02 15:08:31 +01:00
#include "designercontext.h"
#include "designertr.h"
#include "editordata.h"
#include "editorwidget.h"
2008-12-02 12:01:29 +01:00
#include "formeditorw.h"
#include "formwindoweditor.h"
#include "formwindowfile.h"
#include "qtcreatorintegration.h"
2008-12-02 12:01:29 +01:00
#include "settingsmanager.h"
#include "settingspage.h"
#include <widgethost.h>
2008-12-02 12:01:29 +01:00
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
2008-12-02 12:01:29 +01:00
#include <coreplugin/coreconstants.h>
#include <coreplugin/designmode.h>
#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editortoolbar.h>
#include <coreplugin/helpmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/outputpane.h>
#include <utils/infobar.h>
2008-12-09 15:25:01 +01:00
#include <utils/qtcassert.h>
2008-12-02 12:01:29 +01:00
#include <QDesignerFormEditorPluginInterface>
#include <QDesignerFormEditorInterface>
#include <QDesignerComponents>
#include <QDesignerFormWindowManagerInterface>
#include <QDesignerWidgetBoxInterface>
#include <abstractobjectinspector.h>
#include <QDesignerPropertyEditorInterface>
#include <QDesignerActionEditorInterface>
2008-12-02 12:01:29 +01:00
#include <QAction>
#include <QActionGroup>
#include <QApplication>
#include <QCursor>
#include <QDockWidget>
#include <QMenu>
#include <QMessageBox>
#include <QKeySequence>
#include <QPrintDialog>
#include <QPrinter>
#include <QPainter>
#include <QStyle>
#include <QToolBar>
#include <QVBoxLayout>
2008-12-02 12:01:29 +01:00
#include <QDebug>
#include <QSettings>
#include <QPluginLoader>
#include <QTime>
#include <QElapsedTimer>
2008-12-02 12:01:29 +01:00
#include <algorithm>
static const char settingsGroupC[] = "Designer";
2008-12-02 12:01:29 +01:00
/* Actions of the designer plugin:
* Designer provides a toolbar which is subject to a context change (to
2010-01-11 10:22:55 +01:00
* "edit mode" context) when it is focused.
* 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. */
2008-12-02 12:01:29 +01:00
static inline QIcon designerIcon(const QString &iconName)
{
const QIcon icon = QDesignerFormEditorInterface::createIcon(iconName);
2008-12-02 12:01:29 +01:00
if (icon.isNull())
qWarning() << "Unable to locate " << iconName;
return icon;
}
using namespace Core;
2008-12-02 12:01:29 +01:00
using namespace Designer::Constants;
using namespace Utils;
2008-12-02 12:01:29 +01:00
namespace Designer {
namespace Internal {
2009-08-11 15:32:53 +02:00
/* A stub-like, read-only text editor which displays UI files as text. Could be used as a
* read/write editor too, but due to lack of XML editor, highlighting and other such
* functionality, editing is disabled.
* Provides an informational title bar containing a button triggering a
* switch to design mode.
* Internally manages a FormWindowEditor and uses the plain text
* editable embedded in it. */
class DesignerXmlEditorWidget : public TextEditor::TextEditorWidget
{
public:
using TextEditorWidget::TextEditorWidget;
void finalizeInitialization() override
{
setReadOnly(true);
}
};
class FormWindowEditorFactory : public TextEditor::TextEditorFactory
{
public:
FormWindowEditorFactory()
{
setId(K_DESIGNER_XML_EDITOR_ID);
setEditorCreator([]() { return new FormWindowEditor; });
setEditorWidgetCreator([]() { return new Internal::DesignerXmlEditorWidget; });
setUseGenericHighlighter(true);
setDuplicatedSupported(false);
setMarksVisible(false);
}
FormWindowEditor *create(QDesignerFormWindowInterface *form)
{
setDocumentCreator([form]() { return new FormWindowFile(form); });
return qobject_cast<FormWindowEditor *>(createEditor());
}
};
2009-08-11 15:32:53 +02:00
// --------- FormEditorW
class FormEditorData
{
public:
FormEditorData();
~FormEditorData();
void activateEditMode(int id);
void toolChanged(int);
void print();
void setPreviewMenuEnabled(bool e);
void updateShortcut(Command *command);
void fullInit();
void saveSettings(QSettings *s);
void initDesignerSubWindows();
void setupActions();
void setupViewActions();
void addDockViewAction(ActionContainer *viewMenu,
int index,
const Context &context,
const QString &title, Id id);
ActionContainer *createPreviewStyleMenu(QActionGroup *actionGroup);
void critical(const QString &errorMessage);
void bindShortcut(Command *command, QAction *action);
QAction *createEditModeAction(QActionGroup *ag,
const Context &context,
ActionContainer *medit,
const QString &actionName,
Id id,
int toolNumber,
const QString &iconName = QString(),
const QString &keySequence = QString());
Command *addToolAction(QAction *a,
const Context &context, Id id,
ActionContainer *c1, const QString &keySequence = QString(),
Id groupId = Id());
QToolBar *createEditorToolBar() const;
IEditor *createEditor();
2008-12-02 12:01:29 +01:00
public:
QDesignerFormEditorInterface *m_formeditor = nullptr;
QtCreatorIntegration *m_integration = nullptr;
QDesignerFormWindowManagerInterface *m_fwm = nullptr;
FormEditorW::InitializationStage m_initStage = FormEditorW::RegisterPlugins;
QWidget *m_designerSubWindows[DesignerSubWindowCount];
QAction *m_lockAction = nullptr;
QAction *m_resetLayoutAction = nullptr;
QList<IOptionsPage *> m_settingsPages;
QActionGroup *m_actionGroupEditMode = nullptr;
QAction *m_actionPrint = nullptr;
QAction *m_actionPreview = nullptr;
QActionGroup *m_actionGroupPreviewInStyle = nullptr;
QMenu *m_previewInStyleMenu = nullptr;
QAction *m_actionAboutPlugins = nullptr;
Context m_contexts;
QList<Id> m_toolActionIds;
QWidget *m_modeWidget = nullptr;
EditorWidget *m_editorWidget = nullptr;
QWidget *m_editorToolBar = nullptr;
EditorToolBar *m_toolBar = nullptr;
QMap<Command *, QAction *> m_commandToDesignerAction;
FormWindowEditorFactory *m_xmlEditorFactory = nullptr;
};
static FormEditorData *d = nullptr;
static FormEditorW *m_instance = nullptr;
FormEditorData::FormEditorData() :
m_formeditor(QDesignerComponents::createFormEditor(nullptr))
2008-12-02 12:01:29 +01:00
{
if (Designer::Constants::Internal::debug)
2008-12-02 12:01:29 +01:00
qDebug() << Q_FUNC_INFO;
QTC_ASSERT(!d, return);
d = this;
2008-12-02 12:01:29 +01:00
std::fill(m_designerSubWindows, m_designerSubWindows + DesignerSubWindowCount,
static_cast<QWidget *>(nullptr));
2008-12-02 12:01:29 +01:00
m_formeditor->setTopLevel(ICore::mainWindow());
2008-12-02 12:01:29 +01:00
m_formeditor->setSettingsManager(new SettingsManager());
m_fwm = m_formeditor->formWindowManager();
2008-12-09 15:25:01 +01:00
QTC_ASSERT(m_fwm, return);
2008-12-02 12:01:29 +01:00
m_contexts.add(C_FORMEDITOR);
2008-12-02 12:01:29 +01:00
setupActions();
const auto optionPages = m_formeditor->optionsPages();
for (QDesignerOptionsPageInterface *designerPage : optionPages) {
2008-12-02 12:01:29 +01:00
SettingsPage *settingsPage = new SettingsPage(designerPage);
m_settingsPages.append(settingsPage);
}
QObject::connect(EditorManager::instance(), &EditorManager::currentEditorChanged, [this](IEditor *editor) {
if (Designer::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << editor << " of " << m_fwm->formWindowCount();
if (editor && editor->document()->id() == Constants::K_DESIGNER_XML_EDITOR_ID) {
FormWindowEditor *xmlEditor = qobject_cast<FormWindowEditor *>(editor);
QTC_ASSERT(xmlEditor, return);
FormEditorW::ensureInitStage(FormEditorW::FullyInitialized);
SharedTools::WidgetHost *fw = m_editorWidget->formWindowEditorForXmlEditor(xmlEditor);
QTC_ASSERT(fw, return);
m_editorWidget->setVisibleEditor(xmlEditor);
m_fwm->setActiveFormWindow(fw->formWindow());
}
});
m_xmlEditorFactory = new FormWindowEditorFactory;
2008-12-02 12:01:29 +01:00
}
FormEditorData::~FormEditorData()
2008-12-02 12:01:29 +01:00
{
if (m_initStage == FormEditorW::FullyInitialized) {
QSettings *s = ICore::settings();
s->beginGroup(settingsGroupC);
m_editorWidget->saveSettings(s);
s->endGroup();
DesignMode::unregisterDesignWidget(m_modeWidget);
delete m_modeWidget;
m_modeWidget = nullptr;
}
2008-12-02 12:01:29 +01:00
delete m_formeditor;
qDeleteAll(m_settingsPages);
m_settingsPages.clear();
delete m_integration;
delete m_xmlEditorFactory ;
d = nullptr;
}
// Add an actioon to toggle the view state of a dock window
void FormEditorData::addDockViewAction(ActionContainer *viewMenu,
int index, const Context &context,
const QString &title, Id id)
{
if (const QDockWidget *dw = m_editorWidget->designerDockWidgets()[index]) {
QAction *action = dw->toggleViewAction();
action->setText(title);
Command *cmd = addToolAction(action, context, id, viewMenu, QString());
cmd->setAttribute(Command::CA_Hide);
}
}
void FormEditorData::setupViewActions()
{
// Populate "View" menu of form editor menu
ActionContainer *viewMenu = ActionManager::actionContainer(Core::Constants::M_VIEW_VIEWS);
QTC_ASSERT(viewMenu, return);
addDockViewAction(viewMenu, WidgetBoxSubWindow, m_contexts,
Tr::tr("Widget box"), "FormEditor.WidgetBox");
addDockViewAction(viewMenu, ObjectInspectorSubWindow, m_contexts,
Tr::tr("Object Inspector"), "FormEditor.ObjectInspector");
addDockViewAction(viewMenu, PropertyEditorSubWindow, m_contexts,
Tr::tr("Property Editor"), "FormEditor.PropertyEditor");
addDockViewAction(viewMenu, SignalSlotEditorSubWindow, m_contexts,
Tr::tr("Signals && Slots Editor"), "FormEditor.SignalsAndSlotsEditor");
addDockViewAction(viewMenu, ActionEditorSubWindow, m_contexts,
Tr::tr("Action Editor"), "FormEditor.ActionEditor");
// Lock/Reset
Command *cmd = addToolAction(m_editorWidget->menuSeparator1(), m_contexts, "FormEditor.SeparatorLock", viewMenu);
cmd->setAttribute(Command::CA_Hide);
cmd = addToolAction(m_editorWidget->autoHideTitleBarsAction(), m_contexts, "FormEditor.Locked", viewMenu);
cmd->setAttribute(Command::CA_Hide);
cmd = addToolAction(m_editorWidget->menuSeparator2(), m_contexts, "FormEditor.SeparatorReset", viewMenu);
cmd->setAttribute(Command::CA_Hide);
cmd = addToolAction(m_editorWidget->resetLayoutAction(), m_contexts, "FormEditor.ResetToDefaultLayout", viewMenu);
QObject::connect(m_editorWidget, &EditorWidget::resetLayout,
m_editorWidget, &EditorWidget::resetToDefaultLayout);
cmd->setAttribute(Command::CA_Hide);
2008-12-02 12:01:29 +01:00
}
void FormEditorData::fullInit()
2008-12-02 12:01:29 +01:00
{
QTC_ASSERT(m_initStage == FormEditorW::RegisterPlugins, return);
QElapsedTimer *initTime = nullptr;
if (Designer::Constants::Internal::debug) {
initTime = new QElapsedTimer;
2008-12-02 12:01:29 +01:00
initTime->start();
}
QDesignerComponents::createTaskMenu(m_formeditor, m_instance);
QDesignerComponents::initializePlugins(m_formeditor);
2008-12-02 12:01:29 +01:00
QDesignerComponents::initializeResources();
initDesignerSubWindows();
m_integration = new QtCreatorIntegration(m_formeditor, m_instance);
2008-12-02 12:01:29 +01:00
m_formeditor->setIntegration(m_integration);
// Connect Qt Designer help request to HelpManager.
QObject::connect(m_integration, &QtCreatorIntegration::creatorHelpRequested,
HelpManager::Signals::instance(),
[](const QUrl &url) { HelpManager::showHelpUrl(url, HelpManager::HelpModeAlways); });
2008-12-02 12:01:29 +01:00
/**
* This will initialize our TabOrder, Signals and slots and Buddy editors.
*/
const QList<QObject *> plugins = QPluginLoader::staticInstances() + m_formeditor->pluginInstances();
for (QObject *plugin : plugins) {
2008-12-02 12:01:29 +01:00
if (QDesignerFormEditorPluginInterface *formEditorPlugin = qobject_cast<QDesignerFormEditorPluginInterface*>(plugin)) {
if (!formEditorPlugin->isInitialized())
formEditorPlugin->initialize(m_formeditor);
}
}
if (m_actionAboutPlugins)
m_actionAboutPlugins->setEnabled(true);
if (Designer::Constants::Internal::debug) {
2008-12-02 12:01:29 +01:00
qDebug() << Q_FUNC_INFO << initTime->elapsed() << "ms";
delete initTime;
}
QObject::connect(EditorManager::instance(), &EditorManager::editorsClosed,
[this] (const QList<IEditor *> editors) {
for (IEditor *editor : editors)
m_editorWidget->removeFormWindowEditor(editor);
});
// Nest toolbar and editor widget
m_editorWidget = new EditorWidget;
QSettings *settings = ICore::settings();
settings->beginGroup(settingsGroupC);
m_editorWidget->restoreSettings(settings);
settings->endGroup();
2010-03-10 10:50:11 +01:00
m_editorToolBar = createEditorToolBar();
m_toolBar = new EditorToolBar;
m_toolBar->setToolbarCreationFlags(EditorToolBar::FlagsStandalone);
2010-03-10 10:50:11 +01:00
m_toolBar->setNavigationVisible(false);
m_toolBar->addCenterToolBar(m_editorToolBar);
m_modeWidget = new QWidget;
m_modeWidget->setObjectName("DesignerModeWidget");
auto layout = new QVBoxLayout(m_modeWidget);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
2010-03-10 10:50:11 +01:00
layout->addWidget(m_toolBar);
// Avoid mode switch to 'Edit' mode when the application started by
// 'Run' in 'Design' mode emits output.
auto splitter = new MiniSplitter(Qt::Vertical);
splitter->addWidget(m_editorWidget);
QWidget *outputPane = new OutputPanePlaceHolder(Core::Constants::MODE_DESIGN, splitter);
outputPane->setObjectName("DesignerOutputPanePlaceHolder");
splitter->addWidget(outputPane);
layout->addWidget(splitter);
Context designerContexts = m_contexts;
designerContexts.add(Core::Constants::C_EDITORMANAGER);
ICore::addContextObject(new DesignerContext(designerContexts, m_modeWidget, m_instance));
DesignMode::registerDesignWidget(m_modeWidget, QStringList(FORM_MIMETYPE), m_contexts);
setupViewActions();
m_initStage = FormEditorW::FullyInitialized;
2008-12-02 12:01:29 +01:00
}
void FormEditorData::initDesignerSubWindows()
2008-12-02 12:01:29 +01:00
{
std::fill(m_designerSubWindows, m_designerSubWindows + DesignerSubWindowCount, static_cast<QWidget*>(nullptr));
2008-12-02 12:01:29 +01:00
QDesignerWidgetBoxInterface *wb = QDesignerComponents::createWidgetBox(m_formeditor, nullptr);
wb->setWindowTitle(Tr::tr("Widget Box"));
wb->setObjectName("WidgetBox");
2008-12-02 12:01:29 +01:00
m_formeditor->setWidgetBox(wb);
m_designerSubWindows[WidgetBoxSubWindow] = wb;
QDesignerObjectInspectorInterface *oi = QDesignerComponents::createObjectInspector(m_formeditor, nullptr);
oi->setWindowTitle(Tr::tr("Object Inspector"));
oi->setObjectName("ObjectInspector");
2008-12-02 12:01:29 +01:00
m_formeditor->setObjectInspector(oi);
m_designerSubWindows[ObjectInspectorSubWindow] = oi;
QDesignerPropertyEditorInterface *pe = QDesignerComponents::createPropertyEditor(m_formeditor, nullptr);
pe->setWindowTitle(Tr::tr("Property Editor"));
pe->setObjectName("PropertyEditor");
2008-12-02 12:01:29 +01:00
m_formeditor->setPropertyEditor(pe);
m_designerSubWindows[PropertyEditorSubWindow] = pe;
QWidget *se = QDesignerComponents::createSignalSlotEditor(m_formeditor, nullptr);
se->setWindowTitle(Tr::tr("Signals and Slots Editor"));
se->setObjectName("SignalsAndSlotsEditor");
2008-12-02 12:01:29 +01:00
m_designerSubWindows[SignalSlotEditorSubWindow] = se;
QDesignerActionEditorInterface *ae = QDesignerComponents::createActionEditor(m_formeditor, nullptr);
ae->setWindowTitle(Tr::tr("Action Editor"));
ae->setObjectName("ActionEditor");
2008-12-02 12:01:29 +01:00
m_formeditor->setActionEditor(ae);
m_designerSubWindows[ActionEditorSubWindow] = ae;
m_initStage = FormEditorW::SubwindowsInitialized;
2008-12-02 12:01:29 +01:00
}
QList<IOptionsPage *> FormEditorW::optionsPages()
{
return d->m_settingsPages;
}
2008-12-02 12:01:29 +01:00
void FormEditorW::ensureInitStage(InitializationStage s)
{
if (Designer::Constants::Internal::debug)
2008-12-02 12:01:29 +01:00
qDebug() << Q_FUNC_INFO << s;
if (!d) {
m_instance = new FormEditorW;
d = new FormEditorData;
}
if (d->m_initStage >= s)
2008-12-02 12:01:29 +01:00
return;
QApplication::setOverrideCursor(Qt::WaitCursor);
d->fullInit();
2008-12-02 12:01:29 +01:00
QApplication::restoreOverrideCursor();
}
void FormEditorW::deleteInstance()
2008-12-02 12:01:29 +01:00
{
delete d;
d = nullptr;
delete m_instance;
m_instance = nullptr;
2008-12-02 12:01:29 +01:00
}
IEditor *FormEditorW::createEditor()
2008-12-02 12:01:29 +01:00
{
ensureInitStage(FullyInitialized);
return d->createEditor();
2008-12-02 12:01:29 +01:00
}
void FormEditorData::setupActions()
2008-12-02 12:01:29 +01:00
{
//menus
ActionContainer *medit = ActionManager::actionContainer(Core::Constants::M_EDIT);
ActionContainer *mformtools = ActionManager::actionContainer(M_FORMEDITOR);
2008-12-02 12:01:29 +01:00
//overridden actions
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());
2008-12-02 12:01:29 +01:00
m_actionPrint = new QAction(m_instance);
bindShortcut(ActionManager::registerAction(m_actionPrint, Core::Constants::PRINT, m_contexts), m_actionPrint);
QObject::connect(m_actionPrint, &QAction::triggered, [this]() { print(); });
2008-12-02 12:01:29 +01:00
//'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).
Command *command;
command = ActionManager::registerAction(m_fwm->actionDelete(), "FormEditor.Edit.Delete", m_contexts);
bindShortcut(command, m_fwm->actionDelete());
command->setAttribute(Command::CA_Hide);
2008-12-02 12:01:29 +01:00
medit->addAction(command, Core::Constants::G_EDIT_COPYPASTE);
m_actionGroupEditMode = new QActionGroup(m_instance);
2008-12-02 12:01:29 +01:00
m_actionGroupEditMode->setExclusive(true);
QObject::connect(m_actionGroupEditMode, &QActionGroup::triggered,
[this](QAction *a) { activateEditMode(a->data().toInt()); });
2008-12-02 12:01:29 +01:00
medit->addSeparator(m_contexts, Core::Constants::G_EDIT_OTHER);
2009-07-09 18:27:56 +02:00
m_toolActionIds.push_back("FormEditor.WidgetEditor");
createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
Tr::tr("Edit Widgets"), m_toolActionIds.back(),
EditModeWidgetEditor, "widgettool.png", Tr::tr("F3"));
2008-12-02 12:01:29 +01:00
m_toolActionIds.push_back("FormEditor.SignalsSlotsEditor");
createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
Tr::tr("Edit Signals/Slots"), m_toolActionIds.back(),
EditModeSignalsSlotEditor, "signalslottool.png", Tr::tr("F4"));
2008-12-02 12:01:29 +01:00
m_toolActionIds.push_back("FormEditor.BuddyEditor");
createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
Tr::tr("Edit Buddies"), m_toolActionIds.back(),
EditModeBuddyEditor, "buddytool.png");
2008-12-02 12:01:29 +01:00
m_toolActionIds.push_back("FormEditor.TabOrderEditor");
createEditModeAction(m_actionGroupEditMode, m_contexts, medit,
Tr::tr("Edit Tab Order"), m_toolActionIds.back(),
EditModeTabOrderEditor, "tabordertool.png");
2008-12-02 12:01:29 +01:00
//tool actions
m_toolActionIds.push_back("FormEditor.LayoutHorizontally");
const QString horizLayoutShortcut = useMacShortcuts ? Tr::tr("Meta+Shift+H") : Tr::tr("Ctrl+H");
addToolAction(m_fwm->actionHorizontalLayout(), m_contexts,
m_toolActionIds.back(), mformtools, horizLayoutShortcut);
m_toolActionIds.push_back("FormEditor.LayoutVertically");
const QString vertLayoutShortcut = useMacShortcuts ? Tr::tr("Meta+L") : Tr::tr("Ctrl+L");
addToolAction(m_fwm->actionVerticalLayout(), m_contexts,
m_toolActionIds.back(), mformtools, vertLayoutShortcut);
2008-12-02 12:01:29 +01:00
m_toolActionIds.push_back("FormEditor.SplitHorizontal");
addToolAction(m_fwm->actionSplitHorizontal(), m_contexts,
2008-12-02 12:01:29 +01:00
m_toolActionIds.back(), mformtools);
m_toolActionIds.push_back("FormEditor.SplitVertical");
addToolAction(m_fwm->actionSplitVertical(), m_contexts,
2008-12-02 12:01:29 +01:00
m_toolActionIds.back(), mformtools);
m_toolActionIds.push_back("FormEditor.LayoutForm");
addToolAction(m_fwm->actionFormLayout(), m_contexts,
2008-12-02 12:01:29 +01:00
m_toolActionIds.back(), mformtools);
m_toolActionIds.push_back("FormEditor.LayoutGrid");
const QString gridShortcut = useMacShortcuts ? Tr::tr("Meta+Shift+G") : Tr::tr("Ctrl+G");
addToolAction(m_fwm->actionGridLayout(), m_contexts,
m_toolActionIds.back(), mformtools, gridShortcut);
2008-12-02 12:01:29 +01:00
m_toolActionIds.push_back("FormEditor.LayoutBreak");
addToolAction(m_fwm->actionBreakLayout(), m_contexts,
2008-12-02 12:01:29 +01:00
m_toolActionIds.back(), mformtools);
m_toolActionIds.push_back("FormEditor.LayoutAdjustSize");
const QString adjustShortcut = useMacShortcuts ? Tr::tr("Meta+J") : Tr::tr("Ctrl+J");
addToolAction(m_fwm->actionAdjustSize(), m_contexts,
m_toolActionIds.back(), mformtools, adjustShortcut);
2008-12-02 12:01:29 +01:00
m_toolActionIds.push_back("FormEditor.SimplifyLayout");
addToolAction(m_fwm->actionSimplifyLayout(), m_contexts,
2008-12-02 12:01:29 +01:00
m_toolActionIds.back(), mformtools);
mformtools->addSeparator(m_contexts);
2008-12-02 12:01:29 +01:00
addToolAction(m_fwm->actionLower(), m_contexts, "FormEditor.Lower", mformtools);
addToolAction(m_fwm->actionRaise(), m_contexts, "FormEditor.Raise", mformtools);
2008-12-02 12:01:29 +01:00
// Commands that do not go into the editor toolbar
mformtools->addSeparator(m_contexts);
2008-12-02 12:01:29 +01:00
m_actionPreview = m_fwm->action(QDesignerFormWindowManagerInterface::DefaultPreviewAction);
2008-12-09 15:25:01 +01:00
QTC_ASSERT(m_actionPreview, return);
addToolAction(m_actionPreview, m_contexts, "FormEditor.Preview", mformtools, Tr::tr("Alt+Shift+R"));
2008-12-02 12:01:29 +01:00
// Preview in style...
m_actionGroupPreviewInStyle = m_fwm->actionGroup(QDesignerFormWindowManagerInterface::StyledPreviewActionGroup);
ActionContainer *previewAC = createPreviewStyleMenu(m_actionGroupPreviewInStyle);
m_previewInStyleMenu = previewAC->menu();
mformtools->addMenu(previewAC);
setPreviewMenuEnabled(false);
2008-12-02 12:01:29 +01:00
// Form settings
medit->addSeparator(m_contexts, Core::Constants::G_EDIT_OTHER);
2008-12-02 12:01:29 +01:00
mformtools->addSeparator(m_contexts);
mformtools->addSeparator(m_contexts, Core::Constants::G_DEFAULT_THREE);
QAction *actionFormSettings = m_fwm->action(QDesignerFormWindowManagerInterface::FormWindowSettingsDialogAction);
addToolAction(actionFormSettings, m_contexts, "FormEditor.FormSettings", mformtools,
QString(), Core::Constants::G_DEFAULT_THREE);
mformtools->addSeparator(m_contexts, Core::Constants::G_DEFAULT_THREE);
m_actionAboutPlugins = new QAction(Tr::tr("About Qt Designer Plugins..."), m_instance);
addToolAction(m_actionAboutPlugins, m_contexts, "FormEditor.AboutPlugins", mformtools,
QString(), Core::Constants::G_DEFAULT_THREE);
QObject::connect(m_actionAboutPlugins, &QAction::triggered,
m_fwm, &QDesignerFormWindowManagerInterface::showPluginDialog);
m_actionAboutPlugins->setEnabled(false);
2008-12-02 12:01:29 +01:00
// FWM
QObject::connect(m_fwm, &QDesignerFormWindowManagerInterface::activeFormWindowChanged,
[this] (QDesignerFormWindowInterface *afw) {
m_fwm->closeAllPreviews();
setPreviewMenuEnabled(afw != nullptr);
});
2008-12-02 12:01:29 +01:00
}
QToolBar *FormEditorData::createEditorToolBar() const
2008-12-02 12:01:29 +01:00
{
QToolBar *editorToolBar = new QToolBar;
for (const auto &id : m_toolActionIds) {
Command *cmd = ActionManager::command(id);
2008-12-09 15:25:01 +01:00
QTC_ASSERT(cmd, continue);
2008-12-02 12:01:29 +01:00
QAction *action = cmd->action();
if (!action->icon().isNull()) // Simplify grid has no action yet
editorToolBar->addAction(action);
2008-12-02 12:01:29 +01:00
}
const int size = editorToolBar->style()->pixelMetric(QStyle::PM_SmallIconSize);
editorToolBar->setIconSize(QSize(size, size));
editorToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
return editorToolBar;
2008-12-02 12:01:29 +01:00
}
ActionContainer *FormEditorData::createPreviewStyleMenu(QActionGroup *actionGroup)
2008-12-02 12:01:29 +01:00
{
const QString menuId = M_FORMEDITOR_PREVIEW;
ActionContainer *menuPreviewStyle = ActionManager::createMenu(M_FORMEDITOR_PREVIEW);
menuPreviewStyle->menu()->setTitle(Tr::tr("Preview in"));
2008-12-02 12:01:29 +01:00
// 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 = "DeviceProfile";
const QChar dot = '.';
2008-12-02 12:01:29 +01:00
for (QAction *a : actions) {
2008-12-02 12:01:29 +01:00
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();
Command *command = ActionManager::registerAction(a, Id::fromString(name), m_contexts);
bindShortcut(command, a);
2008-12-02 12:01:29 +01:00
if (isDeviceProfile) {
command->setAttribute(Command::CA_UpdateText);
command->setAttribute(Command::CA_NonConfigurable);
2008-12-02 12:01:29 +01:00
}
menuPreviewStyle->addAction(command);
}
return menuPreviewStyle;
}
void FormEditorData::setPreviewMenuEnabled(bool e)
{
m_actionPreview->setEnabled(e);
m_previewInStyleMenu->setEnabled(e);
}
void FormEditorData::saveSettings(QSettings *s)
2008-12-02 12:01:29 +01:00
{
s->beginGroup(settingsGroupC);
m_editorWidget->saveSettings(s);
s->endGroup();
2008-12-02 12:01:29 +01:00
}
void FormEditorData::critical(const QString &errorMessage)
2008-12-02 12:01:29 +01:00
{
QMessageBox::critical(ICore::dialogParent(), Tr::tr("Designer"), errorMessage);
2008-12-02 12:01:29 +01:00
}
// Apply the command shortcut to the action and connects to the command's keySequenceChanged signal
void FormEditorData::bindShortcut(Command *command, QAction *action)
{
m_commandToDesignerAction.insert(command, action);
QObject::connect(command, &Command::keySequenceChanged,
command, [this, command] { updateShortcut(command); });
updateShortcut(command);
}
// Create an action to activate a designer tool
QAction *FormEditorData::createEditModeAction(QActionGroup *ag,
const Context &context,
ActionContainer *medit,
const QString &actionName,
Id id,
int toolNumber,
const QString &iconName,
const QString &keySequence)
{
auto rc = new QAction(actionName, ag);
rc->setCheckable(true);
if (!iconName.isEmpty())
rc->setIcon(designerIcon(iconName));
Command *command = ActionManager::registerAction(rc, id, context);
command->setAttribute(Command::CA_Hide);
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
Command *FormEditorData::addToolAction(QAction *a, const Context &context, Id id,
ActionContainer *c1, const QString &keySequence,
Id groupId)
{
Command *command = ActionManager::registerAction(a, id, context);
if (!keySequence.isEmpty())
command->setDefaultKeySequence(QKeySequence(keySequence));
if (!a->isSeparator())
bindShortcut(command, a);
c1->addAction(command, groupId);
return command;
}
IEditor *FormEditorData::createEditor()
2008-12-02 12:01:29 +01:00
{
if (Designer::Constants::Internal::debug)
qDebug() << "FormEditorW::createEditor";
// Create and associate form and text editor.
2008-12-02 12:01:29 +01:00
m_fwm->closeAllPreviews();
QDesignerFormWindowInterface *form = m_fwm->createFormWindow(nullptr);
QTC_ASSERT(form, return nullptr);
form->setPalette(Theme::initialPalette());
QObject::connect(form, &QDesignerFormWindowInterface::toolChanged, [this] (int i) { toolChanged(i); });
auto widgetHost = new SharedTools::WidgetHost( /* parent */ nullptr, form);
FormWindowEditor *formWindowEditor = m_xmlEditorFactory->create(form);
2010-03-10 10:50:11 +01:00
m_editorWidget->add(widgetHost, formWindowEditor);
m_toolBar->addEditor(formWindowEditor);
2010-03-10 10:50:11 +01:00
if (formWindowEditor) {
Utils::InfoBarEntry info(Id(Constants::INFO_READ_ONLY),
Tr::tr("This file can only be edited in <b>Design</b> mode."));
info.addCustomButton(Tr::tr("Switch Mode"), []() { ModeManager::activateMode(Core::Constants::MODE_DESIGN); });
formWindowEditor->document()->infoBar()->addInfo(info);
}
return formWindowEditor;
2008-12-02 12:01:29 +01:00
}
QDesignerFormEditorInterface *FormEditorW::designerEditor()
{
ensureInitStage(FullyInitialized);
return d->m_formeditor;
}
QWidget * const *FormEditorW::designerSubWindows()
2008-12-02 12:01:29 +01:00
{
ensureInitStage(SubwindowsInitialized);
return d->m_designerSubWindows;
2008-12-02 12:01:29 +01:00
}
SharedTools::WidgetHost *FormEditorW::activeWidgetHost()
2008-12-02 12:01:29 +01:00
{
ensureInitStage(FullyInitialized);
if (d->m_editorWidget)
return d->m_editorWidget->activeEditor().widgetHost;
return nullptr;
}
2008-12-02 12:01:29 +01:00
FormWindowEditor *FormEditorW::activeEditor()
{
ensureInitStage(FullyInitialized);
if (d->m_editorWidget)
return d->m_editorWidget->activeEditor().formWindowEditor;
return nullptr;
2008-12-02 12:01:29 +01:00
}
void FormEditorData::updateShortcut(Command *command)
2008-12-02 12:01:29 +01:00
{
if (!command)
return;
if (QAction *a = m_commandToDesignerAction.value(command))
a->setShortcut(command->action()->shortcut());
2008-12-02 12:01:29 +01:00
}
void FormEditorData::activateEditMode(int id)
2008-12-02 12:01:29 +01:00
{
if (const int count = m_fwm->formWindowCount())
for (int i = 0; i < count; i++)
m_fwm->formWindow(i)->setCurrentTool(id);
}
void FormEditorData::toolChanged(int t)
2008-12-02 12:01:29 +01:00
{
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;
}
}
void FormEditorData::print()
2008-12-02 12:01:29 +01:00
{
// Printing code courtesy of designer_actions.cpp
QDesignerFormWindowInterface *fw = m_fwm->activeFormWindow();
if (!fw)
return;
QPrinter *printer = ICore::printer();
const bool oldFullPage = printer->fullPage();
const QPageLayout::Orientation oldOrientation = printer->pageLayout().orientation();
printer->setFullPage(false);
2008-12-02 12:01:29 +01:00
do {
// Grab the image to be able to a suggest suitable orientation
QString errorMessage;
const QPixmap pixmap = m_fwm->createPreviewPixmap();
2008-12-02 12:01:29 +01:00
if (pixmap.isNull()) {
critical(Tr::tr("The image could not be created: %1").arg(errorMessage));
2008-12-02 12:01:29 +01:00
break;
}
const QSizeF pixmapSize = pixmap.size();
printer->setPageOrientation(pixmapSize.width() > pixmapSize.height() ? QPageLayout::Landscape
: QPageLayout::Portrait);
2008-12-02 12:01:29 +01:00
// Printer parameters
QPrintDialog dialog(printer, fw);
2008-12-02 12:01:29 +01:00
if (!dialog.exec())
break;
QWidget *mainWindow = ICore::mainWindow();
const QCursor oldCursor = mainWindow->cursor();
mainWindow->setCursor(Qt::WaitCursor);
2008-12-02 12:01:29 +01:00
// Estimate of required scaling to make form look the same on screen and printer.
const double suggestedScaling = static_cast<double>(printer->physicalDpiX()) / static_cast<double>(fw->physicalDpiX());
2008-12-02 12:01:29 +01:00
QPainter painter(printer);
2008-12-02 12:01:29 +01:00
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);
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);
2008-12-02 12:01:29 +01:00
// Draw.
painter.translate(xOffset, yOffset);
painter.scale(scaling, scaling);
painter.drawPixmap(0, 0, pixmap);
mainWindow->setCursor(oldCursor);
2008-12-02 12:01:29 +01:00
} while (false);
printer->setFullPage(oldFullPage);
printer->setPageOrientation(oldOrientation);
2008-12-02 12:01:29 +01:00
}
} // namespace Internal
} // namespace Designer