2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2010-02-26 11:08:17 +01:00
|
|
|
|
|
|
|
|
#include "designmode.h"
|
|
|
|
|
|
2023-01-16 17:20:07 +01:00
|
|
|
#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"
|
2015-11-11 19:26:58 +01:00
|
|
|
|
2018-01-23 10:33:18 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2010-02-26 11:08:17 +01:00
|
|
|
|
Use sidebar buttons for hiding/showing dock areas
So far, if a mode includes navigation widget placeholders, these are
used for the sidebar toggle buttons, otherwise the buttons are disabled.
Now, if a mode does not include navigation widget placeholders, but the
mode has a FancyMainWindow attached, use the buttons to hide or show the
corresponding dock widget area (left or right).
Since QMainWindow does not really support "hiding a dock widget area",
the FancyMainWindow needs to track that state manually, by tracking the
dock widgets that were visible before "hiding the dock widget area".
Also, if a dock widget is dragged into a "hidden" area, or a widget is
made visible or "unfloated" into that area, show the other widgets in the
area again as well, "unhiding" the area.
Since the mode widgets that have a mainwindow somewhere usually wrap
that into a splitter for the output panes, and the Design mode is
actually a stack widget, IMode needs another method that returns the
appropriate FancyMainWindow if available.
The patch implements this for Widget Designer.
Change-Id: I03531f4d5130c846ff5d65831b1c9be210e1c561
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-11-24 09:26:31 +01:00
|
|
|
#include <utils/fancymainwindow.h>
|
|
|
|
|
|
|
|
|
|
#include <aggregation/aggregate.h>
|
|
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDebug>
|
2020-06-26 13:59:38 +02:00
|
|
|
#include <QPointer>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QStackedWidget>
|
2020-06-26 13:59:38 +02:00
|
|
|
#include <QStringList>
|
2010-02-26 11:08:17 +01:00
|
|
|
|
2023-11-28 16:10:37 +01:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2024-05-03 14:08:12 +02:00
|
|
|
/*!
|
|
|
|
|
\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.
|
|
|
|
|
*/
|
|
|
|
|
|
2010-02-26 11:08:17 +01:00
|
|
|
namespace Core {
|
|
|
|
|
|
2011-04-14 12:28:21 +02:00
|
|
|
struct DesignEditorInfo
|
|
|
|
|
{
|
2023-11-28 16:10:37 +01:00
|
|
|
int widgetIndex = -1;
|
2010-03-17 17:44:46 +01:00
|
|
|
QStringList mimeTypes;
|
2010-06-25 12:56:16 +02:00
|
|
|
Context context;
|
2023-11-28 16:10:37 +01:00
|
|
|
QWidget *widget = nullptr;
|
|
|
|
|
FancyMainWindow *mainWindow = nullptr;
|
2010-03-17 17:44:46 +01:00
|
|
|
};
|
|
|
|
|
|
2011-04-14 12:28:21 +02:00
|
|
|
class DesignModePrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
2015-08-26 14:39:15 +02:00
|
|
|
DesignModePrivate();
|
2016-03-14 11:24:27 +02:00
|
|
|
~DesignModePrivate();
|
2011-04-14 12:28:21 +02:00
|
|
|
|
|
|
|
|
public:
|
2014-11-16 10:52:41 +02:00
|
|
|
QPointer<IEditor> m_currentEditor;
|
2018-01-23 09:09:46 +01:00
|
|
|
bool m_isActive = false;
|
2010-03-17 17:44:46 +01:00
|
|
|
QList<DesignEditorInfo*> m_editors;
|
|
|
|
|
QStackedWidget *m_stackWidget;
|
2010-06-25 12:56:16 +02:00
|
|
|
Context m_activeContext;
|
2010-03-17 17:44:46 +01:00
|
|
|
};
|
|
|
|
|
|
2015-08-26 14:39:15 +02:00
|
|
|
DesignModePrivate::DesignModePrivate()
|
2018-01-23 09:09:46 +01:00
|
|
|
: m_stackWidget(new QStackedWidget)
|
2015-08-26 14:39:15 +02:00
|
|
|
{}
|
2010-03-17 17:44:46 +01:00
|
|
|
|
2016-03-14 11:24:27 +02:00
|
|
|
DesignModePrivate::~DesignModePrivate()
|
|
|
|
|
{
|
|
|
|
|
delete m_stackWidget;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-23 09:09:46 +01:00
|
|
|
static DesignMode *m_instance = nullptr;
|
|
|
|
|
static DesignModePrivate *d = nullptr;
|
|
|
|
|
|
2011-04-14 12:28:21 +02:00
|
|
|
DesignMode::DesignMode()
|
2010-02-26 11:08:17 +01:00
|
|
|
{
|
2022-12-07 16:25:11 +01:00
|
|
|
ICore::addPreCloseListener([] {
|
2018-07-21 21:11:46 +02:00
|
|
|
m_instance->currentEditorChanged(nullptr);
|
2015-08-26 14:39:15 +02:00
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
2010-12-03 17:30:09 +01:00
|
|
|
setObjectName(QLatin1String("DesignMode"));
|
2010-02-26 11:08:17 +01:00
|
|
|
setEnabled(false);
|
2011-04-13 13:00:30 +02:00
|
|
|
setContext(Context(Constants::C_DESIGN_MODE));
|
|
|
|
|
setWidget(d->m_stackWidget);
|
2023-01-16 17:20:07 +01:00
|
|
|
setDisplayName(Tr::tr("Design"));
|
2015-11-11 19:26:58 +01:00
|
|
|
setIcon(Utils::Icon::modeIcon(Icons::MODE_DESIGN_CLASSIC,
|
|
|
|
|
Icons::MODE_DESIGN_FLAT, Icons::MODE_DESIGN_FLAT_ACTIVE));
|
2011-04-13 16:09:04 +02:00
|
|
|
setPriority(Constants::P_MODE_DESIGN);
|
2012-05-07 18:28:03 +02:00
|
|
|
setId(Constants::MODE_DESIGN);
|
2011-04-13 13:00:30 +02:00
|
|
|
|
2014-11-16 10:52:41 +02:00
|
|
|
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
|
|
|
|
|
this, &DesignMode::currentEditorChanged);
|
2010-03-19 16:07:04 +01:00
|
|
|
|
2014-11-16 10:52:41 +02:00
|
|
|
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
|
|
|
|
|
this, &DesignMode::updateContext);
|
2010-02-26 11:08:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DesignMode::~DesignMode()
|
|
|
|
|
{
|
2010-03-17 17:44:46 +01:00
|
|
|
qDeleteAll(d->m_editors);
|
2010-02-26 11:08:17 +01:00
|
|
|
}
|
|
|
|
|
|
2011-10-19 13:05:53 +02:00
|
|
|
DesignMode *DesignMode::instance()
|
|
|
|
|
{
|
|
|
|
|
return m_instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DesignMode::setDesignModeIsRequired()
|
|
|
|
|
{
|
2018-01-23 10:33:18 +01:00
|
|
|
// d != nullptr indicates "isRequired".
|
|
|
|
|
if (!d)
|
|
|
|
|
d = new DesignModePrivate;
|
2011-10-19 13:05:53 +02:00
|
|
|
}
|
|
|
|
|
|
2010-03-26 12:39:26 +01:00
|
|
|
/**
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2010-03-19 16:07:04 +01:00
|
|
|
void DesignMode::registerDesignWidget(QWidget *widget,
|
|
|
|
|
const QStringList &mimeTypes,
|
2023-11-28 16:10:37 +01:00
|
|
|
const Context &context,
|
|
|
|
|
Utils::FancyMainWindow *mainWindow)
|
2010-02-26 11:08:17 +01:00
|
|
|
{
|
2011-10-19 13:05:53 +02:00
|
|
|
setDesignModeIsRequired();
|
2010-03-17 17:44:46 +01:00
|
|
|
int index = d->m_stackWidget->addWidget(widget);
|
2018-07-21 21:11:46 +02:00
|
|
|
auto info = new DesignEditorInfo;
|
2010-02-26 11:08:17 +01:00
|
|
|
info->mimeTypes = mimeTypes;
|
2010-03-19 16:07:04 +01:00
|
|
|
info->context = context;
|
2010-02-26 11:08:17 +01:00
|
|
|
info->widgetIndex = index;
|
|
|
|
|
info->widget = widget;
|
2023-11-28 16:10:37 +01:00
|
|
|
info->mainWindow = mainWindow;
|
2010-03-17 17:44:46 +01:00
|
|
|
d->m_editors.append(info);
|
2010-02-26 11:08:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DesignMode::unregisterDesignWidget(QWidget *widget)
|
|
|
|
|
{
|
2010-03-17 17:44:46 +01:00
|
|
|
d->m_stackWidget->removeWidget(widget);
|
2022-10-07 14:46:06 +02:00
|
|
|
for (DesignEditorInfo *info : std::as_const(d->m_editors)) {
|
2010-02-26 11:08:17 +01:00
|
|
|
if (info->widget == widget) {
|
2010-03-17 17:44:46 +01:00
|
|
|
d->m_editors.removeAll(info);
|
2015-01-06 21:07:18 +02:00
|
|
|
delete info;
|
2010-02-26 11:08:17 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if editor changes, check if we have valid mimetype registered.
|
2014-11-16 10:52:41 +02:00
|
|
|
void DesignMode::currentEditorChanged(IEditor *editor)
|
2010-02-26 11:08:17 +01:00
|
|
|
{
|
2010-04-06 15:10:20 +02:00
|
|
|
if (editor && (d->m_currentEditor.data() == editor))
|
2010-03-30 18:16:05 +02:00
|
|
|
return;
|
|
|
|
|
|
2010-02-26 11:08:17 +01:00
|
|
|
bool mimeEditorAvailable = false;
|
|
|
|
|
|
2013-07-04 22:25:15 +02:00
|
|
|
if (editor) {
|
2012-02-14 16:43:51 +01:00
|
|
|
const QString mimeType = editor->document()->mimeType();
|
2010-05-07 14:49:57 +02:00
|
|
|
if (!mimeType.isEmpty()) {
|
2022-10-07 14:46:06 +02:00
|
|
|
for (const DesignEditorInfo *editorInfo : std::as_const(d->m_editors)) {
|
2022-05-02 17:25:11 +02:00
|
|
|
for (const QString &mime : editorInfo->mimeTypes) {
|
2010-05-07 14:49:57 +02:00
|
|
|
if (mime == mimeType) {
|
|
|
|
|
d->m_stackWidget->setCurrentIndex(editorInfo->widgetIndex);
|
2023-11-28 16:10:37 +01:00
|
|
|
setMainWindow(editorInfo->mainWindow);
|
2010-05-07 14:49:57 +02:00
|
|
|
setActiveContext(editorInfo->context);
|
|
|
|
|
mimeEditorAvailable = true;
|
|
|
|
|
setEnabled(true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-05-02 17:25:11 +02:00
|
|
|
}
|
2010-05-07 14:49:57 +02:00
|
|
|
if (mimeEditorAvailable)
|
2010-02-26 11:08:17 +01:00
|
|
|
break;
|
2022-05-02 17:25:11 +02:00
|
|
|
}
|
2010-02-26 11:08:17 +01:00
|
|
|
}
|
|
|
|
|
}
|
2010-03-30 18:16:05 +02:00
|
|
|
if (d->m_currentEditor)
|
2016-02-02 09:10:54 +02:00
|
|
|
disconnect(d->m_currentEditor.data()->document(), &IDocument::changed, this, &DesignMode::updateActions);
|
2010-03-30 18:16:05 +02:00
|
|
|
|
2010-03-19 16:07:04 +01:00
|
|
|
if (!mimeEditorAvailable) {
|
2010-06-25 12:56:16 +02:00
|
|
|
setActiveContext(Context());
|
2018-07-10 15:49:50 +02:00
|
|
|
if (ModeManager::currentModeId() == id())
|
2014-11-16 10:52:41 +02:00
|
|
|
ModeManager::activateMode(Constants::MODE_EDIT);
|
2010-02-26 11:08:17 +01:00
|
|
|
setEnabled(false);
|
2018-07-21 21:11:46 +02:00
|
|
|
d->m_currentEditor = nullptr;
|
2010-03-30 18:16:05 +02:00
|
|
|
emit actionsUpdated(d->m_currentEditor.data());
|
|
|
|
|
} else {
|
2012-09-24 13:48:18 +02:00
|
|
|
d->m_currentEditor = editor;
|
2010-02-26 11:08:17 +01:00
|
|
|
|
2010-03-30 18:16:05 +02:00
|
|
|
if (d->m_currentEditor)
|
2016-02-02 09:10:54 +02:00
|
|
|
connect(d->m_currentEditor.data()->document(), &IDocument::changed, this, &DesignMode::updateActions);
|
2010-02-26 11:08:17 +01:00
|
|
|
|
2010-03-30 18:16:05 +02:00
|
|
|
emit actionsUpdated(d->m_currentEditor.data());
|
|
|
|
|
}
|
2010-02-26 11:08:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DesignMode::updateActions()
|
|
|
|
|
{
|
2010-03-17 17:44:46 +01:00
|
|
|
emit actionsUpdated(d->m_currentEditor.data());
|
2010-02-26 11:08:17 +01:00
|
|
|
}
|
|
|
|
|
|
2020-06-26 13:59:38 +02:00
|
|
|
void DesignMode::updateContext(Utils::Id newMode, Utils::Id oldMode)
|
2010-03-19 16:07:04 +01:00
|
|
|
{
|
2016-03-25 20:00:19 +01:00
|
|
|
if (newMode == id())
|
2014-11-16 11:47:18 +02:00
|
|
|
ICore::addAdditionalContext(d->m_activeContext);
|
2016-03-25 20:00:19 +01:00
|
|
|
else if (oldMode == id())
|
2014-11-16 11:47:18 +02:00
|
|
|
ICore::removeAdditionalContext(d->m_activeContext);
|
2010-03-19 16:07:04 +01:00
|
|
|
}
|
|
|
|
|
|
2010-06-25 12:56:16 +02:00
|
|
|
void DesignMode::setActiveContext(const Context &context)
|
2010-03-19 16:07:04 +01:00
|
|
|
{
|
2010-06-25 18:05:09 +02:00
|
|
|
if (d->m_activeContext == context)
|
2010-03-19 16:07:04 +01:00
|
|
|
return;
|
|
|
|
|
|
2018-07-10 15:49:50 +02:00
|
|
|
if (ModeManager::currentModeId() == id())
|
2014-11-16 10:52:41 +02:00
|
|
|
ICore::updateAdditionalContexts(d->m_activeContext, context);
|
2010-03-22 18:05:22 +01:00
|
|
|
|
2010-03-19 16:07:04 +01:00
|
|
|
d->m_activeContext = context;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-23 10:33:18 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-26 11:08:17 +01:00
|
|
|
} // namespace Core
|