forked from qt-creator/qt-creator
Fixes: QTCREATORBUG-30756 Change-Id: Icb4a2513e230b71b5bb5033ead6a09ad3a8963ab Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
240 lines
6.4 KiB
C++
240 lines
6.4 KiB
C++
// Copyright (C) 2016 The Qt Company Ltd.
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
|
|
#include "designmode.h"
|
|
|
|
#include "coreconstants.h"
|
|
#include "coreicons.h"
|
|
#include "coreplugintr.h"
|
|
#include "editormanager/editormanager.h"
|
|
#include "editormanager/ieditor.h"
|
|
#include "icore.h"
|
|
#include "idocument.h"
|
|
#include "modemanager.h"
|
|
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
#include <utils/fancymainwindow.h>
|
|
|
|
#include <aggregation/aggregate.h>
|
|
|
|
#include <QDebug>
|
|
#include <QPointer>
|
|
#include <QStackedWidget>
|
|
#include <QStringList>
|
|
|
|
using namespace Utils;
|
|
|
|
/*!
|
|
\class Core::DesignMode
|
|
\inmodule QtCreator
|
|
|
|
\brief The DesignMode class implements the mode for the Design mode, which is
|
|
for example used by \QMLD and \QD.
|
|
|
|
Other plugins can register themselves with registerDesignWidget(),
|
|
giving a list of MIME types that the editor understands, as well as an instance
|
|
to the main editor widget itself.
|
|
*/
|
|
|
|
namespace Core {
|
|
|
|
struct DesignEditorInfo
|
|
{
|
|
int widgetIndex = -1;
|
|
QStringList mimeTypes;
|
|
Context context;
|
|
QWidget *widget = nullptr;
|
|
FancyMainWindow *mainWindow = nullptr;
|
|
};
|
|
|
|
class DesignModePrivate
|
|
{
|
|
public:
|
|
DesignModePrivate();
|
|
~DesignModePrivate();
|
|
|
|
public:
|
|
QPointer<IEditor> m_currentEditor;
|
|
bool m_isActive = false;
|
|
QList<DesignEditorInfo*> m_editors;
|
|
QStackedWidget *m_stackWidget;
|
|
Context m_activeContext;
|
|
};
|
|
|
|
DesignModePrivate::DesignModePrivate()
|
|
: m_stackWidget(new QStackedWidget)
|
|
{}
|
|
|
|
DesignModePrivate::~DesignModePrivate()
|
|
{
|
|
delete m_stackWidget;
|
|
}
|
|
|
|
static DesignMode *m_instance = nullptr;
|
|
static DesignModePrivate *d = nullptr;
|
|
|
|
DesignMode::DesignMode()
|
|
{
|
|
ICore::addPreCloseListener([] {
|
|
m_instance->currentEditorChanged(nullptr);
|
|
return true;
|
|
});
|
|
|
|
setObjectName(QLatin1String("DesignMode"));
|
|
setEnabled(false);
|
|
setContext(Context(Constants::C_DESIGN_MODE));
|
|
setWidget(d->m_stackWidget);
|
|
setDisplayName(Tr::tr("Design"));
|
|
setIcon(Utils::Icon::modeIcon(Icons::MODE_DESIGN_CLASSIC,
|
|
Icons::MODE_DESIGN_FLAT, Icons::MODE_DESIGN_FLAT_ACTIVE));
|
|
setPriority(Constants::P_MODE_DESIGN);
|
|
setId(Constants::MODE_DESIGN);
|
|
|
|
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
|
|
this, &DesignMode::currentEditorChanged);
|
|
|
|
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
|
|
this, &DesignMode::updateContext);
|
|
}
|
|
|
|
DesignMode::~DesignMode()
|
|
{
|
|
qDeleteAll(d->m_editors);
|
|
}
|
|
|
|
DesignMode *DesignMode::instance()
|
|
{
|
|
return m_instance;
|
|
}
|
|
|
|
void DesignMode::setDesignModeIsRequired()
|
|
{
|
|
// d != nullptr indicates "isRequired".
|
|
if (!d)
|
|
d = new DesignModePrivate;
|
|
}
|
|
|
|
/**
|
|
* Registers a widget to be displayed when an editor with a file specified in
|
|
* mimeTypes is opened. This also appends the additionalContext in ICore to
|
|
* the context, specified here.
|
|
*/
|
|
void DesignMode::registerDesignWidget(QWidget *widget,
|
|
const QStringList &mimeTypes,
|
|
const Context &context,
|
|
Utils::FancyMainWindow *mainWindow)
|
|
{
|
|
setDesignModeIsRequired();
|
|
int index = d->m_stackWidget->addWidget(widget);
|
|
auto info = new DesignEditorInfo;
|
|
info->mimeTypes = mimeTypes;
|
|
info->context = context;
|
|
info->widgetIndex = index;
|
|
info->widget = widget;
|
|
info->mainWindow = mainWindow;
|
|
d->m_editors.append(info);
|
|
}
|
|
|
|
void DesignMode::unregisterDesignWidget(QWidget *widget)
|
|
{
|
|
d->m_stackWidget->removeWidget(widget);
|
|
for (DesignEditorInfo *info : std::as_const(d->m_editors)) {
|
|
if (info->widget == widget) {
|
|
d->m_editors.removeAll(info);
|
|
delete info;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if editor changes, check if we have valid mimetype registered.
|
|
void DesignMode::currentEditorChanged(IEditor *editor)
|
|
{
|
|
if (editor && (d->m_currentEditor.data() == editor))
|
|
return;
|
|
|
|
bool mimeEditorAvailable = false;
|
|
|
|
if (editor) {
|
|
const QString mimeType = editor->document()->mimeType();
|
|
if (!mimeType.isEmpty()) {
|
|
for (const DesignEditorInfo *editorInfo : std::as_const(d->m_editors)) {
|
|
for (const QString &mime : editorInfo->mimeTypes) {
|
|
if (mime == mimeType) {
|
|
d->m_stackWidget->setCurrentIndex(editorInfo->widgetIndex);
|
|
setMainWindow(editorInfo->mainWindow);
|
|
setActiveContext(editorInfo->context);
|
|
mimeEditorAvailable = true;
|
|
setEnabled(true);
|
|
break;
|
|
}
|
|
}
|
|
if (mimeEditorAvailable)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (d->m_currentEditor)
|
|
disconnect(d->m_currentEditor.data()->document(), &IDocument::changed, this, &DesignMode::updateActions);
|
|
|
|
if (!mimeEditorAvailable) {
|
|
setActiveContext(Context());
|
|
if (ModeManager::currentModeId() == id())
|
|
ModeManager::activateMode(Constants::MODE_EDIT);
|
|
setEnabled(false);
|
|
d->m_currentEditor = nullptr;
|
|
emit actionsUpdated(d->m_currentEditor.data());
|
|
} else {
|
|
d->m_currentEditor = editor;
|
|
|
|
if (d->m_currentEditor)
|
|
connect(d->m_currentEditor.data()->document(), &IDocument::changed, this, &DesignMode::updateActions);
|
|
|
|
emit actionsUpdated(d->m_currentEditor.data());
|
|
}
|
|
}
|
|
|
|
void DesignMode::updateActions()
|
|
{
|
|
emit actionsUpdated(d->m_currentEditor.data());
|
|
}
|
|
|
|
void DesignMode::updateContext(Utils::Id newMode, Utils::Id oldMode)
|
|
{
|
|
if (newMode == id())
|
|
ICore::addAdditionalContext(d->m_activeContext);
|
|
else if (oldMode == id())
|
|
ICore::removeAdditionalContext(d->m_activeContext);
|
|
}
|
|
|
|
void DesignMode::setActiveContext(const Context &context)
|
|
{
|
|
if (d->m_activeContext == context)
|
|
return;
|
|
|
|
if (ModeManager::currentModeId() == id())
|
|
ICore::updateAdditionalContexts(d->m_activeContext, context);
|
|
|
|
d->m_activeContext = context;
|
|
}
|
|
|
|
void DesignMode::createModeIfRequired()
|
|
{
|
|
if (d) {
|
|
m_instance = new DesignMode;
|
|
ExtensionSystem::PluginManager::addObject(m_instance);
|
|
}
|
|
}
|
|
|
|
void DesignMode::destroyModeIfRequired()
|
|
{
|
|
if (m_instance) {
|
|
ExtensionSystem::PluginManager::removeObject(m_instance);
|
|
delete m_instance;
|
|
}
|
|
delete d;
|
|
}
|
|
|
|
} // namespace Core
|