2016-01-15 14:57:40 +01:00
|
|
|
/****************************************************************************
|
2015-08-31 18:06:36 +02:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 Jochen Becher
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2015-08-31 18:06:36 +02:00
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator.
|
|
|
|
|
**
|
|
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2015-08-31 18:06:36 +02:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2015-08-31 18:06:36 +02:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "modeleditor.h"
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
#include "actionhandler.h"
|
|
|
|
|
#include "diagramsviewmanager.h"
|
|
|
|
|
#include "dragtool.h"
|
|
|
|
|
#include "editordiagramview.h"
|
|
|
|
|
#include "elementtasks.h"
|
2015-08-31 18:06:36 +02:00
|
|
|
#include "extdocumentcontroller.h"
|
2016-02-16 21:48:50 +01:00
|
|
|
#include "extpropertiesmview.h"
|
2015-09-21 12:11:02 +02:00
|
|
|
#include "modeldocument.h"
|
|
|
|
|
#include "modeleditor_constants.h"
|
|
|
|
|
#include "modeleditor_plugin.h"
|
|
|
|
|
#include "modelsmanager.h"
|
|
|
|
|
#include "openelementvisitor.h"
|
|
|
|
|
#include "uicontroller.h"
|
2015-08-31 18:06:36 +02:00
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
#include "qmt/controller/undocontroller.h"
|
|
|
|
|
#include "qmt/diagram/dpackage.h"
|
|
|
|
|
#include "qmt/diagram_controller/diagramcontroller.h"
|
2018-01-07 20:31:02 +01:00
|
|
|
#include "qmt/diagram_controller/dcontainer.h"
|
|
|
|
|
#include "qmt/diagram_controller/dreferences.h"
|
2015-09-21 12:11:02 +02:00
|
|
|
#include "qmt/diagram_controller/dselection.h"
|
|
|
|
|
#include "qmt/diagram_scene/diagramscenemodel.h"
|
|
|
|
|
#include "qmt/diagram_ui/diagram_mime_types.h"
|
2015-08-31 18:06:36 +02:00
|
|
|
#include "qmt/diagram_ui/diagramsmanager.h"
|
2015-09-21 12:11:02 +02:00
|
|
|
#include "qmt/model/mpackage.h"
|
|
|
|
|
#include "qmt/model/mclass.h"
|
|
|
|
|
#include "qmt/model/mcomponent.h"
|
2015-08-31 18:06:36 +02:00
|
|
|
#include "qmt/model/mcanvasdiagram.h"
|
|
|
|
|
#include "qmt/model_controller/modelcontroller.h"
|
2018-01-07 20:31:02 +01:00
|
|
|
#include "qmt/model_controller/mcontainer.h"
|
|
|
|
|
#include "qmt/model_controller/mreferences.h"
|
2015-09-21 12:11:02 +02:00
|
|
|
#include "qmt/model_controller/mselection.h"
|
|
|
|
|
#include "qmt/model_ui/treemodel.h"
|
|
|
|
|
#include "qmt/model_ui/treemodelmanager.h"
|
|
|
|
|
#include "qmt/model_widgets_ui/modeltreeview.h"
|
|
|
|
|
#include "qmt/model_widgets_ui/propertiesview.h"
|
|
|
|
|
#include "qmt/stereotype/shapepaintvisitor.h"
|
|
|
|
|
#include "qmt/stereotype/stereotypecontroller.h"
|
|
|
|
|
#include "qmt/stereotype/stereotypeicon.h"
|
|
|
|
|
#include "qmt/stereotype/toolbar.h"
|
|
|
|
|
#include "qmt/style/style.h"
|
|
|
|
|
#include "qmt/style/stylecontroller.h"
|
|
|
|
|
#include "qmt/tasks/diagramscenecontroller.h"
|
2015-09-25 17:18:50 +02:00
|
|
|
#include "qmt/tasks/finddiagramvisitor.h"
|
2015-08-31 18:06:36 +02:00
|
|
|
|
2018-02-01 16:33:34 +01:00
|
|
|
#include <coreplugin/actionmanager/actionmanager.h>
|
|
|
|
|
#include <coreplugin/actionmanager/command.h>
|
2015-09-21 12:11:02 +02:00
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
|
|
|
|
#include <coreplugin/minisplitter.h>
|
|
|
|
|
#include <coreplugin/actionmanager/commandbutton.h>
|
2016-06-24 22:44:37 +02:00
|
|
|
#include <utils/fadingindicator.h>
|
2015-09-21 12:11:02 +02:00
|
|
|
#include <utils/styledbar.h>
|
|
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
|
|
|
|
#include <QAction>
|
2020-07-13 18:27:48 +02:00
|
|
|
#include <QActionGroup>
|
2015-09-25 09:47:34 +02:00
|
|
|
#include <QComboBox>
|
2015-09-21 12:11:02 +02:00
|
|
|
#include <QDir>
|
|
|
|
|
#include <QEvent>
|
2016-02-22 20:59:28 +01:00
|
|
|
#include <QFileDialog>
|
2015-08-31 18:06:36 +02:00
|
|
|
#include <QFileInfo>
|
2015-09-21 12:11:02 +02:00
|
|
|
#include <QFrame>
|
|
|
|
|
#include <QHBoxLayout>
|
2016-02-22 20:59:28 +01:00
|
|
|
#include <QImageWriter>
|
2015-09-21 12:11:02 +02:00
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QMap>
|
2016-02-22 20:59:28 +01:00
|
|
|
#include <QMessageBox>
|
2015-09-21 12:11:02 +02:00
|
|
|
#include <QPainter>
|
|
|
|
|
#include <QPixmap>
|
|
|
|
|
#include <QScrollArea>
|
|
|
|
|
#include <QStackedWidget>
|
|
|
|
|
#include <QStyleFactory>
|
|
|
|
|
#include <QTimer>
|
|
|
|
|
#include <QToolBox>
|
|
|
|
|
#include <QUndoStack>
|
|
|
|
|
#include <QVBoxLayout>
|
2016-06-24 18:53:54 +02:00
|
|
|
#include <QMenu>
|
2018-08-09 14:53:40 +02:00
|
|
|
#include <QScrollBar>
|
2015-08-31 18:06:36 +02:00
|
|
|
|
2015-12-31 10:36:57 +01:00
|
|
|
#include <algorithm>
|
|
|
|
|
|
2015-08-31 18:06:36 +02:00
|
|
|
namespace ModelEditor {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2015-12-03 21:31:56 +01:00
|
|
|
static const char PROPERTYNAME_TOOLBARID[] = "ToolbarId";
|
2016-06-21 21:27:43 +02:00
|
|
|
static const double ZOOM_FACTOR = 1.05;
|
2015-12-03 21:31:56 +01:00
|
|
|
|
2015-08-31 18:06:36 +02:00
|
|
|
class ModelEditor::ModelEditorPrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
2017-07-30 22:12:58 +02:00
|
|
|
UiController *uiController = nullptr;
|
|
|
|
|
ActionHandler *actionHandler = nullptr;
|
|
|
|
|
ModelDocument *document = nullptr;
|
|
|
|
|
qmt::PropertiesView *propertiesView = nullptr;
|
|
|
|
|
Core::MiniSplitter *rightSplitter = nullptr;
|
|
|
|
|
QWidget *leftGroup = nullptr;
|
|
|
|
|
QHBoxLayout *leftGroupLayout = nullptr;
|
|
|
|
|
QToolBox *leftToolBox = nullptr;
|
|
|
|
|
QStackedWidget *diagramStack = nullptr;
|
|
|
|
|
EditorDiagramView *diagramView = nullptr;
|
|
|
|
|
QLabel *noDiagramLabel = nullptr;
|
|
|
|
|
DiagramsViewManager *diagramsViewManager = nullptr;
|
|
|
|
|
Core::MiniSplitter *rightHorizSplitter = nullptr;
|
|
|
|
|
qmt::ModelTreeView *modelTreeView = nullptr;
|
|
|
|
|
qmt::TreeModelManager *modelTreeViewServant = nullptr;
|
|
|
|
|
QScrollArea *propertiesScrollArea = nullptr;
|
|
|
|
|
QWidget *propertiesGroupWidget = nullptr;
|
|
|
|
|
QWidget *toolbar = nullptr;
|
|
|
|
|
QComboBox *diagramSelector = nullptr;
|
2015-09-21 12:11:02 +02:00
|
|
|
SelectedArea selectedArea = SelectedArea::Nothing;
|
2016-02-22 20:59:28 +01:00
|
|
|
QString lastExportDirPath;
|
2017-07-30 22:12:58 +02:00
|
|
|
QAction *syncBrowserWithDiagramAction = nullptr;
|
|
|
|
|
QAction *syncDiagramWithBrowserAction = nullptr;
|
|
|
|
|
QAction *syncEachOtherAction = nullptr;
|
2015-08-31 18:06:36 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ModelEditor::ModelEditor(UiController *uiController, ActionHandler *actionHandler, QWidget *parent)
|
2015-09-21 12:11:02 +02:00
|
|
|
: IEditor(parent),
|
2015-08-31 18:06:36 +02:00
|
|
|
d(new ModelEditorPrivate)
|
|
|
|
|
{
|
|
|
|
|
setContext(Core::Context(Constants::MODEL_EDITOR_ID));
|
2015-09-21 12:11:02 +02:00
|
|
|
d->uiController = uiController;
|
|
|
|
|
d->actionHandler = actionHandler;
|
2015-08-31 18:06:36 +02:00
|
|
|
d->document = new ModelDocument(this);
|
|
|
|
|
connect(d->document, &ModelDocument::contentSet, this, &ModelEditor::onContentSet);
|
|
|
|
|
init(parent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ModelEditor::~ModelEditor()
|
|
|
|
|
{
|
2015-09-25 15:25:23 +02:00
|
|
|
closeCurrentDiagram(false);
|
2015-09-21 12:11:02 +02:00
|
|
|
delete d->toolbar;
|
2015-08-31 18:06:36 +02:00
|
|
|
delete d;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-25 20:47:14 +03:00
|
|
|
Core::IDocument *ModelEditor::document() const
|
2015-08-31 18:06:36 +02:00
|
|
|
{
|
|
|
|
|
return d->document;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
QWidget *ModelEditor::toolBar()
|
|
|
|
|
{
|
|
|
|
|
return d->toolbar;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 15:25:23 +02:00
|
|
|
QByteArray ModelEditor::saveState() const
|
|
|
|
|
{
|
|
|
|
|
return saveState(currentDiagram());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ModelEditor::restoreState(const QByteArray &state)
|
|
|
|
|
{
|
|
|
|
|
QDataStream stream(state);
|
|
|
|
|
int version = 0;
|
|
|
|
|
stream >> version;
|
2016-06-24 18:53:54 +02:00
|
|
|
if (version >= 1) {
|
2015-09-25 15:25:23 +02:00
|
|
|
qmt::Uid uid;
|
|
|
|
|
stream >> uid;
|
2016-06-24 18:53:54 +02:00
|
|
|
if (version >= 2) {
|
|
|
|
|
bool sync = false;
|
|
|
|
|
bool syncBrowserWithDiagram = false;
|
|
|
|
|
bool syncDiagramWithBrowser = false;
|
|
|
|
|
bool syncEachOther = false;
|
|
|
|
|
stream >> sync >> syncBrowserWithDiagram >> syncDiagramWithBrowser >> syncEachOther;
|
|
|
|
|
d->actionHandler->synchronizeBrowserAction()->setChecked(sync);
|
|
|
|
|
d->syncBrowserWithDiagramAction->setChecked(
|
|
|
|
|
syncBrowserWithDiagram || (!syncDiagramWithBrowser && !syncEachOther));
|
|
|
|
|
d->syncDiagramWithBrowserAction->setChecked(syncDiagramWithBrowser);
|
|
|
|
|
d->syncEachOtherAction->setChecked(syncEachOther);
|
|
|
|
|
}
|
2015-09-25 15:25:23 +02:00
|
|
|
if (uid.isValid()) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MDiagram *diagram = d->document->documentController()->modelController()->findObject<qmt::MDiagram>(uid);
|
2015-09-25 15:25:23 +02:00
|
|
|
if (diagram) {
|
|
|
|
|
openDiagram(diagram, false);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
void ModelEditor::init(QWidget *parent)
|
|
|
|
|
{
|
|
|
|
|
// create and configure properties view
|
|
|
|
|
d->propertiesView = new qmt::PropertiesView(this);
|
|
|
|
|
|
|
|
|
|
// create and configure editor ui
|
|
|
|
|
d->rightSplitter = new Core::MiniSplitter(parent);
|
|
|
|
|
connect(d->rightSplitter, &QSplitter::splitterMoved,
|
|
|
|
|
this, &ModelEditor::onRightSplitterMoved);
|
|
|
|
|
connect(d->uiController, &UiController::rightSplitterChanged,
|
|
|
|
|
this, &ModelEditor::onRightSplitterChanged);
|
|
|
|
|
|
|
|
|
|
d->leftGroup = new QWidget(d->rightSplitter);
|
|
|
|
|
d->leftGroupLayout = new QHBoxLayout(d->leftGroup);
|
|
|
|
|
d->leftGroupLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
d->leftGroupLayout->setSpacing(0);
|
|
|
|
|
|
|
|
|
|
d->leftToolBox = new QToolBox(d->leftGroup);
|
|
|
|
|
// Windows style does not truncate the tab label to a very small width (GTK+ does)
|
2017-07-30 21:38:49 +02:00
|
|
|
static QStyle *windowsStyle = QStyleFactory().create("Windows");
|
2015-09-21 12:11:02 +02:00
|
|
|
if (windowsStyle)
|
|
|
|
|
d->leftToolBox->setStyle(windowsStyle);
|
|
|
|
|
// TODO improve this (and the diagram colors) for use with dark theme
|
|
|
|
|
d->leftToolBox->setStyleSheet(
|
|
|
|
|
QLatin1String("QToolBox::tab {"
|
|
|
|
|
" margin-left: 2px;"
|
|
|
|
|
" background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
|
|
|
|
|
" stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,"
|
|
|
|
|
" stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);"
|
|
|
|
|
" color: #606060;"
|
|
|
|
|
"}"
|
|
|
|
|
""
|
|
|
|
|
"QToolBox::tab:selected {"
|
|
|
|
|
" font: italic;"
|
|
|
|
|
" color: black;"
|
|
|
|
|
"}"));
|
|
|
|
|
QFont font = d->leftToolBox->font();
|
|
|
|
|
font.setPointSizeF(font.pointSizeF() * 0.8);
|
|
|
|
|
d->leftToolBox->setFont(font);
|
2015-12-03 21:31:56 +01:00
|
|
|
connect(d->leftToolBox, &QToolBox::currentChanged, this, &ModelEditor::onToolbarSelectionChanged);
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
d->diagramStack = new QStackedWidget(d->leftGroup);
|
|
|
|
|
|
|
|
|
|
d->diagramView = new EditorDiagramView(d->diagramStack);
|
|
|
|
|
d->diagramStack->addWidget(d->diagramView);
|
|
|
|
|
|
|
|
|
|
d->noDiagramLabel = new QLabel(d->diagramStack);
|
2015-12-03 21:31:56 +01:00
|
|
|
const QString placeholderText =
|
|
|
|
|
tr("<html><body style=\"color:#909090; font-size:14px\">"
|
|
|
|
|
"<div align='center'>"
|
|
|
|
|
"<div style=\"font-size:20px\">Open a diagram</div>"
|
|
|
|
|
"<table><tr><td>"
|
|
|
|
|
"<hr/>"
|
|
|
|
|
"<div style=\"margin-top: 5px\">• Double-click on diagram in model tree</div>"
|
|
|
|
|
"<div style=\"margin-top: 5px\">• Select \"Open Diagram\" from package's context menu in model tree</div>"
|
|
|
|
|
"</td></tr></table>"
|
|
|
|
|
"</div>"
|
|
|
|
|
"</body></html>");
|
2015-09-21 12:11:02 +02:00
|
|
|
d->noDiagramLabel->setText(placeholderText);
|
|
|
|
|
d->diagramStack->addWidget(d->noDiagramLabel);
|
|
|
|
|
d->diagramStack->setCurrentWidget(d->noDiagramLabel);
|
|
|
|
|
|
|
|
|
|
d->leftGroupLayout->addWidget(d->leftToolBox, 0);
|
|
|
|
|
auto frame = new QFrame(d->leftGroup);
|
|
|
|
|
frame->setFrameShape(QFrame::VLine);
|
|
|
|
|
d->leftGroupLayout->addWidget(frame, 0);
|
|
|
|
|
d->leftGroupLayout->addWidget(d->diagramStack, 1);
|
|
|
|
|
|
|
|
|
|
d->rightHorizSplitter = new Core::MiniSplitter(d->rightSplitter);
|
|
|
|
|
d->rightHorizSplitter->setOrientation(Qt::Vertical);
|
|
|
|
|
connect(d->rightHorizSplitter, &QSplitter::splitterMoved,
|
|
|
|
|
this, &ModelEditor::onRightHorizSplitterMoved);
|
|
|
|
|
connect(d->uiController, &UiController::rightHorizSplitterChanged,
|
|
|
|
|
this, &ModelEditor::onRightHorizSplitterChanged);
|
|
|
|
|
|
|
|
|
|
d->modelTreeView = new qmt::ModelTreeView(d->rightHorizSplitter);
|
|
|
|
|
d->modelTreeView->setFrameShape(QFrame::NoFrame);
|
|
|
|
|
|
|
|
|
|
d->modelTreeViewServant = new qmt::TreeModelManager(this);
|
|
|
|
|
d->modelTreeViewServant->setModelTreeView(d->modelTreeView);
|
|
|
|
|
|
|
|
|
|
d->propertiesScrollArea = new QScrollArea(d->rightHorizSplitter);
|
|
|
|
|
d->propertiesScrollArea->setFrameShape(QFrame::NoFrame);
|
|
|
|
|
d->propertiesScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
2015-10-06 20:35:07 +02:00
|
|
|
d->propertiesScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
2015-09-21 12:11:02 +02:00
|
|
|
d->propertiesScrollArea->setWidgetResizable(true);
|
|
|
|
|
|
|
|
|
|
d->rightHorizSplitter->insertWidget(0, d->modelTreeView);
|
|
|
|
|
d->rightHorizSplitter->insertWidget(1, d->propertiesScrollArea);
|
|
|
|
|
d->rightHorizSplitter->setStretchFactor(0, 2); // magic stretch factors for equal sizing
|
|
|
|
|
d->rightHorizSplitter->setStretchFactor(1, 3);
|
|
|
|
|
|
|
|
|
|
d->rightSplitter->insertWidget(0, d->leftGroup);
|
|
|
|
|
d->rightSplitter->insertWidget(1, d->rightHorizSplitter);
|
|
|
|
|
d->rightSplitter->setStretchFactor(0, 1);
|
|
|
|
|
d->rightSplitter->setStretchFactor(1, 0);
|
|
|
|
|
|
|
|
|
|
setWidget(d->rightSplitter);
|
|
|
|
|
|
|
|
|
|
// restore splitter sizes after any stretch factor has been set as fallback
|
|
|
|
|
if (d->uiController->hasRightSplitterState())
|
|
|
|
|
d->rightSplitter->restoreState(d->uiController->rightSplitterState());
|
|
|
|
|
if (d->uiController->hasRightHorizSplitterState())
|
|
|
|
|
d->rightHorizSplitter->restoreState(d->uiController->rightHorizSplitterState());
|
|
|
|
|
|
|
|
|
|
// create and configure toolbar
|
|
|
|
|
d->toolbar = new QWidget();
|
|
|
|
|
auto toolbarLayout = new QHBoxLayout(d->toolbar);
|
|
|
|
|
toolbarLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
toolbarLayout->setSpacing(0);
|
2015-09-25 17:18:50 +02:00
|
|
|
|
|
|
|
|
auto openParentButton = new Core::CommandButton(Constants::OPEN_PARENT_DIAGRAM, d->toolbar);
|
|
|
|
|
openParentButton->setDefaultAction(d->actionHandler->openParentDiagramAction());
|
|
|
|
|
toolbarLayout->addWidget(openParentButton);
|
|
|
|
|
|
2015-09-25 09:47:34 +02:00
|
|
|
d->diagramSelector = new QComboBox(d->toolbar);
|
2019-02-26 09:40:49 +01:00
|
|
|
connect(d->diagramSelector, QOverload<int>::of(&QComboBox::activated),
|
2015-09-25 09:47:34 +02:00
|
|
|
this, &ModelEditor::onDiagramSelectorSelected);
|
|
|
|
|
toolbarLayout->addWidget(d->diagramSelector, 1);
|
|
|
|
|
toolbarLayout->addStretch(1);
|
2015-09-25 17:18:50 +02:00
|
|
|
|
2018-02-01 16:38:19 +01:00
|
|
|
toolbarLayout->addWidget(createToolbarCommandButton(Core::Constants::ZOOM_RESET,
|
|
|
|
|
[this]() { resetZoom(); },
|
|
|
|
|
d->toolbar));
|
|
|
|
|
toolbarLayout->addWidget(createToolbarCommandButton(Core::Constants::ZOOM_IN,
|
|
|
|
|
[this]() { zoomIn(); },
|
|
|
|
|
d->toolbar));
|
|
|
|
|
toolbarLayout->addWidget(createToolbarCommandButton(Core::Constants::ZOOM_OUT,
|
|
|
|
|
[this]() { zoomOut(); },
|
|
|
|
|
d->toolbar));
|
2018-02-01 16:33:34 +01:00
|
|
|
toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_PACKAGE,
|
|
|
|
|
[this]() { onAddPackage(); },
|
|
|
|
|
d->toolbar));
|
|
|
|
|
toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_COMPONENT,
|
|
|
|
|
[this]() { onAddComponent(); },
|
|
|
|
|
d->toolbar));
|
|
|
|
|
toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_CLASS,
|
|
|
|
|
[this]() { onAddClass(); },
|
|
|
|
|
d->toolbar));
|
|
|
|
|
toolbarLayout->addWidget(createToolbarCommandButton(Constants::ACTION_ADD_CANVAS_DIAGRAM,
|
|
|
|
|
[this]() { onAddCanvasDiagram(); },
|
|
|
|
|
d->toolbar));
|
2015-09-25 09:47:34 +02:00
|
|
|
toolbarLayout->addSpacing(20);
|
2016-06-24 18:53:54 +02:00
|
|
|
|
|
|
|
|
auto syncToggleButton = new Core::CommandButton(Constants::ACTION_SYNC_BROWSER, d->toolbar);
|
|
|
|
|
syncToggleButton->setDefaultAction(d->actionHandler->synchronizeBrowserAction());
|
|
|
|
|
QMenu *syncMenu = new QMenu(syncToggleButton);
|
|
|
|
|
QActionGroup *syncGroup = new QActionGroup(syncMenu);
|
2017-07-30 21:38:49 +02:00
|
|
|
d->syncBrowserWithDiagramAction = syncMenu->addAction(tr("Synchronize Structure with Diagram"));
|
2016-06-24 18:53:54 +02:00
|
|
|
d->syncBrowserWithDiagramAction->setCheckable(true);
|
|
|
|
|
d->syncBrowserWithDiagramAction->setActionGroup(syncGroup);
|
2017-07-30 21:38:49 +02:00
|
|
|
d->syncDiagramWithBrowserAction = syncMenu->addAction(tr("Synchronize Diagram with Structure"));
|
2016-06-24 18:53:54 +02:00
|
|
|
d->syncDiagramWithBrowserAction->setCheckable(true);
|
|
|
|
|
d->syncDiagramWithBrowserAction->setActionGroup(syncGroup);
|
2017-07-30 21:38:49 +02:00
|
|
|
d->syncEachOtherAction = syncMenu->addAction(tr("Keep Synchronized"));
|
2016-06-24 18:53:54 +02:00
|
|
|
d->syncEachOtherAction->setCheckable(true);
|
|
|
|
|
d->syncEachOtherAction->setActionGroup(syncGroup);
|
|
|
|
|
syncToggleButton->setMenu(syncMenu);
|
|
|
|
|
d->syncBrowserWithDiagramAction->setChecked(true);
|
|
|
|
|
toolbarLayout->addWidget(syncToggleButton);
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::initDocument()
|
|
|
|
|
{
|
2018-08-10 10:49:05 +02:00
|
|
|
if (d->diagramsViewManager)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
initToolbars();
|
|
|
|
|
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
|
|
|
|
d->diagramView->setPxNodeController(documentController->pxNodeController());
|
|
|
|
|
|
|
|
|
|
d->diagramsViewManager = new DiagramsViewManager(this);
|
|
|
|
|
connect(d->diagramsViewManager, &DiagramsViewManager::openNewDiagram,
|
|
|
|
|
this, &ModelEditor::showDiagram);
|
|
|
|
|
connect(d->diagramsViewManager, &DiagramsViewManager::closeOpenDiagram,
|
|
|
|
|
this, &ModelEditor::closeDiagram);
|
|
|
|
|
connect(d->diagramsViewManager, &DiagramsViewManager::closeAllOpenDiagrams,
|
|
|
|
|
this, &ModelEditor::closeAllDiagrams);
|
2015-11-04 22:44:41 +01:00
|
|
|
documentController->diagramsManager()->setDiagramsView(d->diagramsViewManager);
|
2015-09-21 12:11:02 +02:00
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
d->propertiesView->setDiagramController(documentController->diagramController());
|
|
|
|
|
d->propertiesView->setModelController(documentController->modelController());
|
|
|
|
|
d->propertiesView->setStereotypeController(documentController->stereotypeController());
|
|
|
|
|
d->propertiesView->setStyleController(documentController->styleController());
|
2016-02-16 21:48:50 +01:00
|
|
|
d->propertiesView->setMViewFactory([=](qmt::PropertiesView *view) {
|
|
|
|
|
auto extView = new ExtPropertiesMView(view);
|
|
|
|
|
extView->setProjectController(documentController->projectController());
|
|
|
|
|
return extView;
|
|
|
|
|
});
|
2015-09-21 12:11:02 +02:00
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
d->modelTreeView->setTreeModel(documentController->sortedTreeModel());
|
2015-09-21 12:11:02 +02:00
|
|
|
d->modelTreeView->setElementTasks(documentController->elementTasks());
|
|
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
d->modelTreeViewServant->setTreeModel(documentController->treeModel());
|
2015-09-21 12:11:02 +02:00
|
|
|
|
2018-01-07 20:31:02 +01:00
|
|
|
connect(ModelEditorPlugin::modelsManager(), &ModelsManager::diagramClipboardChanged,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onDiagramClipboardChanged, Qt::QueuedConnection);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->undoController()->undoStack(), &QUndoStack::canUndoChanged,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onCanUndoChanged, Qt::QueuedConnection);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->undoController()->undoStack(), &QUndoStack::canRedoChanged,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onCanRedoChanged, Qt::QueuedConnection);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->treeModel(), &qmt::TreeModel::modelReset,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onTreeModelReset, Qt::QueuedConnection);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->diagramController(), &qmt::DiagramController::modified,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onDiagramModified, Qt::QueuedConnection);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->diagramsManager(), &qmt::DiagramsManager::diagramSelectionChanged,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onDiagramSelectionChanged, Qt::QueuedConnection);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->diagramsManager(), &qmt::DiagramsManager::diagramActivated,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onDiagramActivated, Qt::QueuedConnection);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->diagramSceneController(), &qmt::DiagramSceneController::newElementCreated,
|
2015-09-21 12:11:02 +02:00
|
|
|
this, &ModelEditor::onNewElementCreated, Qt::QueuedConnection);
|
|
|
|
|
|
|
|
|
|
connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
|
|
|
|
|
this, &ModelEditor::onCurrentEditorChanged, Qt::QueuedConnection);
|
|
|
|
|
|
2016-06-24 22:44:37 +02:00
|
|
|
connect(d->diagramView, &EditorDiagramView::zoomIn,
|
2018-08-09 14:53:40 +02:00
|
|
|
this, &ModelEditor::zoomInAtPos);
|
2016-06-24 22:44:37 +02:00
|
|
|
connect(d->diagramView, &EditorDiagramView::zoomOut,
|
2018-08-09 14:53:40 +02:00
|
|
|
this, &ModelEditor::zoomOutAtPos);
|
2016-06-24 22:44:37 +02:00
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
connect(d->modelTreeView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
|
|
|
this, &ModelEditor::onTreeViewSelectionChanged, Qt::QueuedConnection);
|
|
|
|
|
connect(d->modelTreeView, &qmt::ModelTreeView::treeViewActivated,
|
|
|
|
|
this, &ModelEditor::onTreeViewActivated, Qt::QueuedConnection);
|
|
|
|
|
connect(d->modelTreeView, &QAbstractItemView::doubleClicked,
|
|
|
|
|
this, &ModelEditor::onTreeViewDoubleClicked, Qt::QueuedConnection);
|
|
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->modelController(), &qmt::ModelController::endMoveObject,
|
2015-09-25 09:47:34 +02:00
|
|
|
this, &ModelEditor::updateDiagramSelector);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->modelController(), &qmt::ModelController::endRemoveObject,
|
2015-09-25 09:47:34 +02:00
|
|
|
this, &ModelEditor::updateDiagramSelector);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->modelController(), &qmt::ModelController::endResetModel,
|
2015-09-25 09:47:34 +02:00
|
|
|
this, &ModelEditor::updateDiagramSelector);
|
2015-11-04 22:44:41 +01:00
|
|
|
connect(documentController->modelController(), &qmt::ModelController::endUpdateObject,
|
2015-09-25 09:47:34 +02:00
|
|
|
this, &ModelEditor::updateDiagramSelector);
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
updateSelectedArea(SelectedArea::Nothing);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qmt::MDiagram *ModelEditor::currentDiagram() const
|
|
|
|
|
{
|
2015-11-04 22:44:41 +01:00
|
|
|
if (!d->diagramView->diagramSceneModel())
|
2019-07-31 17:21:41 +02:00
|
|
|
return nullptr;
|
2015-11-04 22:44:41 +01:00
|
|
|
return d->diagramView->diagramSceneModel()->diagram();
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::showDiagram(qmt::MDiagram *diagram)
|
|
|
|
|
{
|
2015-09-25 15:25:23 +02:00
|
|
|
openDiagram(diagram, true);
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::undo()
|
|
|
|
|
{
|
2015-11-04 22:44:41 +01:00
|
|
|
d->document->documentController()->undoController()->undoStack()->undo();
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::redo()
|
|
|
|
|
{
|
2015-11-04 22:44:41 +01:00
|
|
|
d->document->documentController()->undoController()->undoStack()->redo();
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::cut()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
2018-01-07 20:31:02 +01:00
|
|
|
ModelsManager *modelsManager = ModelEditorPlugin::modelsManager();
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
switch (d->selectedArea) {
|
|
|
|
|
case SelectedArea::Nothing:
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::Diagram:
|
2018-01-07 20:31:02 +01:00
|
|
|
setDiagramClipboard(documentController->cutFromDiagram(currentDiagram()));
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
case SelectedArea::TreeView:
|
2018-01-07 20:31:02 +01:00
|
|
|
modelsManager->setModelClipboard(documentController, documentController->cutFromModel(d->modelTreeViewServant->selectedObjects()));
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::copy()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
2018-01-07 20:31:02 +01:00
|
|
|
ModelsManager *modelsManager = ModelEditorPlugin::modelsManager();
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
switch (d->selectedArea) {
|
|
|
|
|
case SelectedArea::Nothing:
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::Diagram:
|
|
|
|
|
if (documentController->hasDiagramSelection(currentDiagram()))
|
2018-01-07 20:31:02 +01:00
|
|
|
setDiagramClipboard(documentController->copyFromDiagram(currentDiagram()));
|
2015-09-21 12:11:02 +02:00
|
|
|
else
|
|
|
|
|
documentController->copyDiagram(currentDiagram());
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::TreeView:
|
2018-01-07 20:31:02 +01:00
|
|
|
modelsManager->setModelClipboard(documentController, documentController->copyFromModel(d->modelTreeViewServant->selectedObjects()));
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::paste()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
2018-01-07 20:31:02 +01:00
|
|
|
ModelsManager *modelsManager = ModelEditorPlugin::modelsManager();
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
switch (d->selectedArea) {
|
|
|
|
|
case SelectedArea::Nothing:
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::Diagram:
|
2018-01-07 20:31:02 +01:00
|
|
|
// on cut/copy diagram and model elements were copied.
|
|
|
|
|
documentController->pasteIntoModel(currentDiagram(), modelsManager->modelClipboard(), qmt::ModelController::PasteOnlyNewElements);
|
|
|
|
|
documentController->pasteIntoDiagram(currentDiagram(), modelsManager->diagramClipboard());
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
case SelectedArea::TreeView:
|
2018-01-07 20:31:02 +01:00
|
|
|
documentController->pasteIntoModel(d->modelTreeViewServant->selectedObject(), modelsManager->modelClipboard(),
|
|
|
|
|
documentController == modelsManager->modelClipboardDocumentController()
|
|
|
|
|
? qmt::ModelController::PasteAlwaysWithNewKeys : qmt::ModelController::PasteAlwaysAndKeepKeys);
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::removeSelectedElements()
|
|
|
|
|
{
|
|
|
|
|
switch (d->selectedArea) {
|
|
|
|
|
case SelectedArea::Nothing:
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::Diagram:
|
|
|
|
|
d->document->documentController()->removeFromDiagram(currentDiagram());
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::TreeView:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::deleteSelectedElements()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
|
|
|
|
switch (d->selectedArea) {
|
|
|
|
|
case SelectedArea::Nothing:
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::Diagram:
|
|
|
|
|
documentController->deleteFromDiagram(currentDiagram());
|
|
|
|
|
break;
|
|
|
|
|
case SelectedArea::TreeView:
|
2015-11-04 22:44:41 +01:00
|
|
|
documentController->deleteFromModel(d->modelTreeViewServant->selectedObjects());
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::selectAll()
|
|
|
|
|
{
|
|
|
|
|
d->document->documentController()->selectAllOnDiagram(currentDiagram());
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 17:18:50 +02:00
|
|
|
void ModelEditor::openParentDiagram()
|
|
|
|
|
{
|
|
|
|
|
qmt::MDiagram *diagram = currentDiagram();
|
|
|
|
|
if (diagram)
|
|
|
|
|
d->document->documentController()->elementTasks()->openParentDiagram(diagram);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
void ModelEditor::editProperties()
|
|
|
|
|
{
|
|
|
|
|
d->propertiesView->editSelectedElement();
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-27 16:19:33 +01:00
|
|
|
void ModelEditor::editSelectedItem()
|
|
|
|
|
{
|
|
|
|
|
onEditSelectedElement();
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-31 13:15:45 +01:00
|
|
|
void ModelEditor::exportDiagram()
|
|
|
|
|
{
|
|
|
|
|
exportToImage(/*selectedElements=*/false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::exportSelectedElements()
|
|
|
|
|
{
|
|
|
|
|
exportToImage(/*selectedElements=*/true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::exportToImage(bool selectedElements)
|
2016-02-22 20:59:28 +01:00
|
|
|
{
|
|
|
|
|
qmt::MDiagram *diagram = currentDiagram();
|
|
|
|
|
if (diagram) {
|
|
|
|
|
if (d->lastExportDirPath.isEmpty())
|
|
|
|
|
d->lastExportDirPath = d->document->filePath().toFileInfo().canonicalPath();
|
2016-02-25 19:57:13 +01:00
|
|
|
QString filter = tr("Images (*.png *.jpeg *.jpg *.tif *.tiff);;PDF (*.pdf)");
|
|
|
|
|
#ifndef QT_NO_SVG
|
|
|
|
|
filter += tr(";;SVG (*.svg)");
|
|
|
|
|
#endif // QT_NO_SVG
|
2016-02-22 20:59:28 +01:00
|
|
|
QString fileName = QFileDialog::getSaveFileName(
|
|
|
|
|
Core::ICore::dialogParent(),
|
2017-12-22 20:25:39 +01:00
|
|
|
selectedElements ? tr("Export Selected Elements") : tr("Export Diagram"),
|
|
|
|
|
d->lastExportDirPath, filter);
|
2016-02-22 20:59:28 +01:00
|
|
|
if (!fileName.isEmpty()) {
|
|
|
|
|
qmt::DocumentController *documentController = d->document->documentController();
|
|
|
|
|
qmt::DiagramSceneModel *sceneModel = documentController->diagramsManager()->diagramSceneModel(diagram);
|
|
|
|
|
bool success = false;
|
|
|
|
|
QString suffix = QFileInfo(fileName).suffix().toLower();
|
|
|
|
|
// TODO use QFileDialog::selectedNameFilter() as fallback if no suffix is given
|
|
|
|
|
if (suffix.isEmpty()) {
|
2017-07-30 21:38:49 +02:00
|
|
|
suffix = "png";
|
|
|
|
|
fileName += ".png";
|
2016-02-22 20:59:28 +01:00
|
|
|
}
|
2017-07-30 21:38:49 +02:00
|
|
|
if (suffix == "pdf")
|
2017-12-22 20:25:39 +01:00
|
|
|
success = sceneModel->exportPdf(fileName, selectedElements);
|
2016-02-25 19:57:13 +01:00
|
|
|
#ifndef QT_NO_SVG
|
2017-07-30 21:38:49 +02:00
|
|
|
else if (suffix == "svg")
|
2017-12-22 20:25:39 +01:00
|
|
|
success = sceneModel->exportSvg(fileName, selectedElements);
|
2016-02-25 19:57:13 +01:00
|
|
|
#endif // QT_NO_SVG
|
2016-02-22 20:59:28 +01:00
|
|
|
else
|
2017-12-22 20:25:39 +01:00
|
|
|
success = sceneModel->exportImage(fileName, selectedElements);
|
2016-02-22 20:59:28 +01:00
|
|
|
if (success)
|
|
|
|
|
d->lastExportDirPath = QFileInfo(fileName).canonicalPath();
|
2017-12-22 20:25:39 +01:00
|
|
|
else if (selectedElements)
|
|
|
|
|
QMessageBox::critical(Core::ICore::dialogParent(), tr("Exporting Selected Elements Failed"),
|
|
|
|
|
tr("Exporting the selected elements of the current diagram into file<br>\"%1\"<br>failed.").arg(fileName));
|
2016-02-22 20:59:28 +01:00
|
|
|
else
|
|
|
|
|
QMessageBox::critical(Core::ICore::dialogParent(), tr("Exporting Diagram Failed"),
|
|
|
|
|
tr("Exporting the diagram into file<br>\"%1\"<br>failed.").arg(fileName));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-21 21:27:43 +02:00
|
|
|
void ModelEditor::zoomIn()
|
|
|
|
|
{
|
|
|
|
|
QTransform transform = d->diagramView->transform();
|
|
|
|
|
transform.scale(ZOOM_FACTOR, ZOOM_FACTOR);
|
|
|
|
|
d->diagramView->setTransform(transform);
|
2016-06-24 22:44:37 +02:00
|
|
|
showZoomIndicator();
|
2016-06-21 21:27:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::zoomOut()
|
|
|
|
|
{
|
|
|
|
|
QTransform transform = d->diagramView->transform();
|
|
|
|
|
transform.scale(1.0 / ZOOM_FACTOR, 1.0 / ZOOM_FACTOR);
|
|
|
|
|
d->diagramView->setTransform(transform);
|
2016-06-24 22:44:37 +02:00
|
|
|
showZoomIndicator();
|
2016-06-21 21:27:43 +02:00
|
|
|
}
|
|
|
|
|
|
2018-08-09 14:53:40 +02:00
|
|
|
void ModelEditor::zoomInAtPos(const QPoint &pos)
|
|
|
|
|
{
|
|
|
|
|
zoomAtPos(pos, ZOOM_FACTOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::zoomOutAtPos(const QPoint &pos)
|
|
|
|
|
{
|
|
|
|
|
zoomAtPos(pos, 1.0 / ZOOM_FACTOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::zoomAtPos(const QPoint &pos, double scale)
|
|
|
|
|
{
|
|
|
|
|
QPointF scenePos = d->diagramView->mapToScene(pos);
|
|
|
|
|
QTransform transform = d->diagramView->transform();
|
|
|
|
|
transform.scale(scale, scale);
|
|
|
|
|
d->diagramView->setTransform(transform);
|
|
|
|
|
QPoint scaledPos = d->diagramView->mapFromScene(scenePos);
|
|
|
|
|
QPoint delta = pos - scaledPos;
|
|
|
|
|
QScrollBar *hBar = d->diagramView->horizontalScrollBar();
|
|
|
|
|
if (hBar)
|
|
|
|
|
hBar->setValue(hBar->value() - delta.x());
|
|
|
|
|
QScrollBar *vBar = d->diagramView->verticalScrollBar();
|
|
|
|
|
if (vBar)
|
|
|
|
|
vBar->setValue(vBar->value() - delta.y());
|
|
|
|
|
showZoomIndicator();
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-21 21:27:43 +02:00
|
|
|
void ModelEditor::resetZoom()
|
|
|
|
|
{
|
|
|
|
|
d->diagramView->setTransform(QTransform());
|
2016-06-24 22:44:37 +02:00
|
|
|
showZoomIndicator();
|
2016-06-21 21:27:43 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
qmt::MPackage *ModelEditor::guessSelectedPackage() const
|
|
|
|
|
{
|
2017-07-30 22:12:58 +02:00
|
|
|
qmt::MPackage *package = nullptr;
|
2015-09-21 12:11:02 +02:00
|
|
|
switch (d->selectedArea) {
|
|
|
|
|
case SelectedArea::Nothing:
|
2015-11-04 22:44:41 +01:00
|
|
|
package = d->modelTreeViewServant->selectedPackage();
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
case SelectedArea::Diagram:
|
|
|
|
|
{
|
|
|
|
|
qmt::DocumentController *documentController = d->document->documentController();
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::DiagramsManager *diagramsManager = documentController->diagramsManager();
|
2015-09-21 12:11:02 +02:00
|
|
|
qmt::MDiagram *diagram = currentDiagram();
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::DSelection selection = diagramsManager->diagramSceneModel(diagram)->selectedElements();
|
|
|
|
|
if (selection.indices().size() == 1) {
|
|
|
|
|
qmt::DPackage *diagramElement = documentController->diagramController()->findElement<qmt::DPackage>(selection.indices().at(0).elementKey(), diagram);
|
2015-09-21 12:11:02 +02:00
|
|
|
if (diagramElement)
|
2015-11-04 22:44:41 +01:00
|
|
|
package = documentController->modelController()->findObject<qmt::MPackage>(diagramElement->modelUid());
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SelectedArea::TreeView:
|
2015-11-04 22:44:41 +01:00
|
|
|
package = d->modelTreeViewServant->selectedPackage();
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return package;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::updateSelectedArea(SelectedArea selectedArea)
|
|
|
|
|
{
|
|
|
|
|
d->selectedArea = selectedArea;
|
|
|
|
|
|
|
|
|
|
qmt::DocumentController *documentController = d->document->documentController();
|
2018-01-07 20:31:02 +01:00
|
|
|
ModelsManager *modelsManager = ModelEditorPlugin::modelsManager();
|
2015-09-21 12:11:02 +02:00
|
|
|
bool canCutCopyDelete = false;
|
|
|
|
|
bool canRemove = false;
|
|
|
|
|
bool canPaste = false;
|
|
|
|
|
bool canSelectAll = false;
|
|
|
|
|
bool canCopyDiagram = false;
|
2015-09-25 17:18:50 +02:00
|
|
|
bool canOpenParentDiagram = false;
|
2016-03-10 18:36:47 +01:00
|
|
|
bool canExportDiagram = false;
|
2017-12-22 20:25:39 +01:00
|
|
|
bool canExportSelectedElements = false;
|
2015-09-21 12:11:02 +02:00
|
|
|
QList<qmt::MElement *> propertiesModelElements;
|
|
|
|
|
QList<qmt::DElement *> propertiesDiagramElements;
|
2017-07-30 22:12:58 +02:00
|
|
|
qmt::MDiagram *propertiesDiagram = nullptr;
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
qmt::MDiagram *activeDiagram = currentDiagram();
|
|
|
|
|
switch (d->selectedArea) {
|
|
|
|
|
case SelectedArea::Nothing:
|
2015-11-04 22:44:41 +01:00
|
|
|
canSelectAll = activeDiagram && !activeDiagram->diagramElements().isEmpty();
|
2017-07-30 22:12:58 +02:00
|
|
|
canExportDiagram = activeDiagram != nullptr;
|
2015-09-21 12:11:02 +02:00
|
|
|
break;
|
|
|
|
|
case SelectedArea::Diagram:
|
|
|
|
|
{
|
|
|
|
|
if (activeDiagram) {
|
2015-11-04 22:44:41 +01:00
|
|
|
bool hasSelection = documentController->diagramsManager()->diagramSceneModel(activeDiagram)->hasSelection();
|
2015-09-21 12:11:02 +02:00
|
|
|
canCutCopyDelete = hasSelection;
|
|
|
|
|
canRemove = hasSelection;
|
2018-01-07 20:31:02 +01:00
|
|
|
canPaste = !modelsManager->isDiagramClipboardEmpty();
|
2015-11-04 22:44:41 +01:00
|
|
|
canSelectAll = !activeDiagram->diagramElements().isEmpty();
|
2015-09-21 12:11:02 +02:00
|
|
|
canCopyDiagram = !hasSelection;
|
2017-12-22 20:25:39 +01:00
|
|
|
canExportDiagram = true;
|
|
|
|
|
canExportSelectedElements = hasSelection;
|
2015-09-21 12:11:02 +02:00
|
|
|
if (hasSelection) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::DSelection selection = documentController->diagramsManager()->diagramSceneModel(activeDiagram)->selectedElements();
|
2015-09-21 12:11:02 +02:00
|
|
|
if (!selection.isEmpty()) {
|
2015-11-04 22:44:41 +01:00
|
|
|
foreach (qmt::DSelection::Index index, selection.indices()) {
|
|
|
|
|
qmt::DElement *diagramElement = documentController->diagramController()->findElement(index.elementKey(), activeDiagram);
|
2015-09-21 12:11:02 +02:00
|
|
|
if (diagramElement)
|
|
|
|
|
propertiesDiagramElements.append(diagramElement);
|
|
|
|
|
}
|
|
|
|
|
if (!propertiesDiagramElements.isEmpty())
|
|
|
|
|
propertiesDiagram = activeDiagram;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SelectedArea::TreeView:
|
|
|
|
|
{
|
2015-11-04 22:44:41 +01:00
|
|
|
bool hasSelection = !d->modelTreeViewServant->selectedObjects().isEmpty();
|
|
|
|
|
bool hasSingleSelection = d->modelTreeViewServant->selectedObjects().indices().size() == 1;
|
2015-09-21 12:11:02 +02:00
|
|
|
canCutCopyDelete = hasSelection && !d->modelTreeViewServant->isRootPackageSelected();
|
2018-01-07 20:31:02 +01:00
|
|
|
canPaste = hasSingleSelection && !modelsManager->isModelClipboardEmpty();
|
2015-11-04 22:44:41 +01:00
|
|
|
canSelectAll = activeDiagram && !activeDiagram->diagramElements().isEmpty();
|
2017-12-22 20:25:39 +01:00
|
|
|
canExportDiagram = activeDiagram != nullptr;
|
2015-11-04 22:44:41 +01:00
|
|
|
QModelIndexList indexes = d->modelTreeView->selectedSourceModelIndexes();
|
2015-09-21 12:11:02 +02:00
|
|
|
if (!indexes.isEmpty()) {
|
|
|
|
|
foreach (const QModelIndex &propertiesIndex, indexes) {
|
|
|
|
|
if (propertiesIndex.isValid()) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MElement *modelElement = documentController->treeModel()->element(propertiesIndex);
|
2015-09-21 12:11:02 +02:00
|
|
|
if (modelElement)
|
|
|
|
|
propertiesModelElements.append(modelElement);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-09-25 17:18:50 +02:00
|
|
|
canOpenParentDiagram = d->document->documentController()->elementTasks()->hasParentDiagram(currentDiagram());
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
d->actionHandler->cutAction()->setEnabled(canCutCopyDelete);
|
|
|
|
|
d->actionHandler->copyAction()->setEnabled(canCutCopyDelete || canCopyDiagram);
|
|
|
|
|
d->actionHandler->pasteAction()->setEnabled(canPaste);
|
|
|
|
|
d->actionHandler->removeAction()->setEnabled(canRemove);
|
|
|
|
|
d->actionHandler->deleteAction()->setEnabled(canCutCopyDelete);
|
|
|
|
|
d->actionHandler->selectAllAction()->setEnabled(canSelectAll);
|
2015-09-25 17:18:50 +02:00
|
|
|
d->actionHandler->openParentDiagramAction()->setEnabled(canOpenParentDiagram);
|
2016-03-10 18:36:47 +01:00
|
|
|
d->actionHandler->exportDiagramAction()->setEnabled(canExportDiagram);
|
2017-12-22 20:25:39 +01:00
|
|
|
d->actionHandler->exportSelectedElementsAction()->setEnabled(canExportSelectedElements);
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
if (!propertiesModelElements.isEmpty())
|
|
|
|
|
showProperties(propertiesModelElements);
|
|
|
|
|
else if (!propertiesDiagramElements.isEmpty())
|
|
|
|
|
showProperties(propertiesDiagram, propertiesDiagramElements);
|
|
|
|
|
else
|
|
|
|
|
clearProperties();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::showProperties(const QList<qmt::MElement *> &modelElements)
|
|
|
|
|
{
|
2015-11-04 22:44:41 +01:00
|
|
|
if (modelElements != d->propertiesView->selectedModelElements()) {
|
2015-09-21 12:11:02 +02:00
|
|
|
clearProperties();
|
|
|
|
|
if (modelElements.size() > 0) {
|
|
|
|
|
d->propertiesView->setSelectedModelElements(modelElements);
|
2015-11-04 22:44:41 +01:00
|
|
|
d->propertiesGroupWidget = d->propertiesView->widget();
|
2015-09-21 12:11:02 +02:00
|
|
|
d->propertiesScrollArea->setWidget(d->propertiesGroupWidget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::showProperties(qmt::MDiagram *diagram,
|
|
|
|
|
const QList<qmt::DElement *> &diagramElements)
|
|
|
|
|
{
|
2015-11-04 22:44:41 +01:00
|
|
|
if (diagram != d->propertiesView->selectedDiagram()
|
|
|
|
|
|| diagramElements != d->propertiesView->selectedDiagramElements())
|
2015-09-21 12:11:02 +02:00
|
|
|
{
|
|
|
|
|
clearProperties();
|
|
|
|
|
if (diagram && diagramElements.size() > 0) {
|
|
|
|
|
d->propertiesView->setSelectedDiagramElements(diagramElements, diagram);
|
2015-11-04 22:44:41 +01:00
|
|
|
d->propertiesGroupWidget = d->propertiesView->widget();
|
2015-09-21 12:11:02 +02:00
|
|
|
d->propertiesScrollArea->setWidget(d->propertiesGroupWidget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::clearProperties()
|
|
|
|
|
{
|
|
|
|
|
d->propertiesView->clearSelection();
|
|
|
|
|
if (d->propertiesGroupWidget) {
|
|
|
|
|
QWidget *scrollWidget = d->propertiesScrollArea->takeWidget();
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(scrollWidget) // avoid warning in release mode
|
2017-07-09 11:49:13 +02:00
|
|
|
QMT_CHECK(scrollWidget == d->propertiesGroupWidget);
|
2015-09-21 12:11:02 +02:00
|
|
|
d->propertiesGroupWidget->deleteLater();
|
2017-07-30 22:12:58 +02:00
|
|
|
d->propertiesGroupWidget = nullptr;
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::expandModelTreeToDepth(int depth)
|
|
|
|
|
{
|
|
|
|
|
d->modelTreeView->expandToDepth(depth);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 13:59:38 +02:00
|
|
|
QToolButton *ModelEditor::createToolbarCommandButton(const Utils::Id &id,
|
2018-02-01 16:33:34 +01:00
|
|
|
const std::function<void()> &slot,
|
2016-06-24 18:53:54 +02:00
|
|
|
QWidget *parent)
|
2015-09-21 12:11:02 +02:00
|
|
|
{
|
2018-02-01 16:33:34 +01:00
|
|
|
Core::Command *command = Core::ActionManager::command(id);
|
|
|
|
|
QTC_CHECK(command);
|
|
|
|
|
const QString text = command ? command->description() : QString();
|
|
|
|
|
auto action = new QAction(text, this);
|
|
|
|
|
action->setIcon(command ? command->action()->icon() : QIcon());
|
|
|
|
|
auto button = Core::Command::toolButtonWithAppendedShortcut(action, command);
|
|
|
|
|
button->setParent(parent);
|
|
|
|
|
connect(button, &QToolButton::clicked, this, slot);
|
2015-09-21 12:11:02 +02:00
|
|
|
return button;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
Tries to change the \a button icon to the icon specified by \a name
|
|
|
|
|
from the current theme. Returns \c true if icon is updated, \c false
|
|
|
|
|
otherwise.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
bool ModelEditor::updateButtonIconByTheme(QAbstractButton *button, const QString &name)
|
|
|
|
|
{
|
2017-07-09 11:49:13 +02:00
|
|
|
QMT_ASSERT(button, return false);
|
|
|
|
|
QMT_ASSERT(!name.isEmpty(), return false);
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
if (QIcon::hasThemeIcon(name)) {
|
|
|
|
|
button->setIcon(QIcon::fromTheme(name));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-24 22:44:37 +02:00
|
|
|
void ModelEditor::showZoomIndicator()
|
|
|
|
|
{
|
|
|
|
|
int scale = int(d->diagramView->transform().map(QPointF(100, 100)).x() + 0.5);
|
|
|
|
|
Utils::FadingIndicator::showText(d->diagramStack,
|
|
|
|
|
QCoreApplication::translate("ModelEditor",
|
|
|
|
|
"Zoom: %1%").arg(scale),
|
|
|
|
|
Utils::FadingIndicator::SmallText);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
void ModelEditor::onAddPackage()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MPackage *package = documentController->createNewPackage(d->modelTreeViewServant->selectedPackage());
|
2015-11-13 09:31:39 +01:00
|
|
|
d->modelTreeView->selectFromSourceModelIndex(documentController->treeModel()->indexOf(package));
|
2015-09-21 12:11:02 +02:00
|
|
|
QTimer::singleShot(0, this, [this]() { onEditSelectedElement(); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onAddComponent()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MComponent *component = documentController->createNewComponent(d->modelTreeViewServant->selectedPackage());
|
2015-11-13 09:31:39 +01:00
|
|
|
d->modelTreeView->selectFromSourceModelIndex(documentController->treeModel()->indexOf(component));
|
2015-09-21 12:11:02 +02:00
|
|
|
QTimer::singleShot(0, this, [this]() { onEditSelectedElement(); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onAddClass()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MClass *klass = documentController->createNewClass(d->modelTreeViewServant->selectedPackage());
|
2015-11-13 09:31:39 +01:00
|
|
|
d->modelTreeView->selectFromSourceModelIndex(documentController->treeModel()->indexOf(klass));
|
2015-09-21 12:11:02 +02:00
|
|
|
QTimer::singleShot(0, this, [this]() { onEditSelectedElement(); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onAddCanvasDiagram()
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MDiagram *diagram = documentController->createNewCanvasDiagram(d->modelTreeViewServant->selectedPackage());
|
2015-11-13 09:31:39 +01:00
|
|
|
d->modelTreeView->selectFromSourceModelIndex(documentController->treeModel()->indexOf(diagram));
|
2015-09-21 12:11:02 +02:00
|
|
|
QTimer::singleShot(0, this, [this]() { onEditSelectedElement(); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onCurrentEditorChanged(Core::IEditor *editor)
|
|
|
|
|
{
|
|
|
|
|
if (this == editor) {
|
2015-11-04 22:44:41 +01:00
|
|
|
QUndoStack *undoStack = d->document->documentController()->undoController()->undoStack();
|
|
|
|
|
d->actionHandler->undoAction()->setDisabled(!undoStack->canUndo());
|
|
|
|
|
d->actionHandler->redoAction()->setDisabled(!undoStack->canRedo());
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
updateSelectedArea(SelectedArea::Nothing);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onCanUndoChanged(bool canUndo)
|
|
|
|
|
{
|
|
|
|
|
if (this == Core::EditorManager::currentEditor())
|
|
|
|
|
d->actionHandler->undoAction()->setEnabled(canUndo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onCanRedoChanged(bool canRedo)
|
|
|
|
|
{
|
|
|
|
|
if (this == Core::EditorManager::currentEditor())
|
|
|
|
|
d->actionHandler->redoAction()->setEnabled(canRedo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onTreeModelReset()
|
|
|
|
|
{
|
|
|
|
|
updateSelectedArea(SelectedArea::Nothing);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onTreeViewSelectionChanged(const QItemSelection &selected,
|
|
|
|
|
const QItemSelection &deselected)
|
|
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(selected)
|
|
|
|
|
Q_UNUSED(deselected)
|
2015-09-21 12:11:02 +02:00
|
|
|
|
2016-06-24 18:53:54 +02:00
|
|
|
synchronizeDiagramWithBrowser();
|
2015-09-21 12:11:02 +02:00
|
|
|
updateSelectedArea(SelectedArea::TreeView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onTreeViewActivated()
|
|
|
|
|
{
|
|
|
|
|
updateSelectedArea(SelectedArea::TreeView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onTreeViewDoubleClicked(const QModelIndex &index)
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
|
|
|
|
QModelIndex treeModelIndex = d->modelTreeView->mapToSourceModelIndex(index);
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MElement *melement = documentController->treeModel()->element(treeModelIndex);
|
2015-09-21 12:11:02 +02:00
|
|
|
// double click on package is already used for toggeling tree
|
|
|
|
|
if (melement && !dynamic_cast<qmt::MPackage *>(melement))
|
|
|
|
|
documentController->elementTasks()->openElement(melement);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onCurrentDiagramChanged(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
|
|
|
|
if (diagram == currentDiagram()) {
|
|
|
|
|
updateSelectedArea(SelectedArea::Diagram);
|
|
|
|
|
} else {
|
|
|
|
|
updateSelectedArea(SelectedArea::Nothing);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onDiagramActivated(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(diagram)
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
updateSelectedArea(SelectedArea::Diagram);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onDiagramClipboardChanged(bool isEmpty)
|
|
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(isEmpty)
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
if (this == Core::EditorManager::currentEditor())
|
|
|
|
|
updateSelectedArea(d->selectedArea);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onNewElementCreated(qmt::DElement *element, qmt::MDiagram *diagram)
|
|
|
|
|
{
|
|
|
|
|
if (diagram == currentDiagram()) {
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
|
2015-11-04 22:44:41 +01:00
|
|
|
documentController->diagramsManager()->diagramSceneModel(diagram)->selectElement(element);
|
|
|
|
|
qmt::MElement *melement = documentController->modelController()->findElement(element->modelUid());
|
2015-11-04 23:34:44 +01:00
|
|
|
if (!(melement && melement->flags().testFlag(qmt::MElement::ReverseEngineered)))
|
2015-09-21 12:11:02 +02:00
|
|
|
QTimer::singleShot(0, this, [this]() { onEditSelectedElement(); });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onDiagramSelectionChanged(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
2016-06-24 18:53:54 +02:00
|
|
|
if (diagram == currentDiagram()) {
|
|
|
|
|
synchronizeBrowserWithDiagram(diagram);
|
2015-09-21 12:11:02 +02:00
|
|
|
updateSelectedArea(SelectedArea::Diagram);
|
2016-06-24 18:53:54 +02:00
|
|
|
}
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onDiagramModified(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(diagram)
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
updateSelectedArea(d->selectedArea);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onRightSplitterMoved(int pos, int index)
|
|
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(pos)
|
|
|
|
|
Q_UNUSED(index)
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
d->uiController->onRightSplitterChanged(d->rightSplitter->saveState());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onRightSplitterChanged(const QByteArray &state)
|
|
|
|
|
{
|
|
|
|
|
d->rightSplitter->restoreState(state);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onRightHorizSplitterMoved(int pos, int index)
|
|
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(pos)
|
|
|
|
|
Q_UNUSED(index)
|
2015-09-21 12:11:02 +02:00
|
|
|
|
|
|
|
|
d->uiController->onRightHorizSplitterChanged(d->rightHorizSplitter->saveState());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onRightHorizSplitterChanged(const QByteArray &state)
|
|
|
|
|
{
|
|
|
|
|
d->rightHorizSplitter->restoreState(state);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-03 21:31:56 +01:00
|
|
|
void ModelEditor::onToolbarSelectionChanged()
|
|
|
|
|
{
|
|
|
|
|
storeToolbarIdInDiagram(currentDiagram());
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-21 12:11:02 +02:00
|
|
|
void ModelEditor::initToolbars()
|
|
|
|
|
{
|
|
|
|
|
QHash<QString, QWidget *> toolBars;
|
|
|
|
|
qmt::DocumentController *documentController = d->document->documentController();
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::StereotypeController *stereotypeController = documentController->stereotypeController();
|
2015-12-31 10:36:57 +01:00
|
|
|
QList<qmt::Toolbar> toolbars = stereotypeController->toolbars();
|
|
|
|
|
std::stable_sort(toolbars.begin(), toolbars.end(),
|
|
|
|
|
[=](const qmt::Toolbar &lhs, const qmt::Toolbar &rhs) { return lhs.priority() > rhs.priority(); });
|
|
|
|
|
foreach (const qmt::Toolbar &toolbar, toolbars) {
|
2015-11-04 22:44:41 +01:00
|
|
|
QWidget *toolBar = toolBars.value(toolbar.id());
|
2017-07-30 22:12:58 +02:00
|
|
|
QLayout *toolBarLayout = nullptr;
|
2015-09-21 12:11:02 +02:00
|
|
|
if (!toolBar) {
|
|
|
|
|
toolBar = new QWidget(d->leftToolBox);
|
2015-12-03 21:31:56 +01:00
|
|
|
toolBar->setProperty(PROPERTYNAME_TOOLBARID, toolbar.id());
|
2015-09-21 12:11:02 +02:00
|
|
|
toolBarLayout = new QVBoxLayout(toolBar);
|
|
|
|
|
toolBarLayout->setContentsMargins(2, 2, 2, 2);
|
|
|
|
|
toolBarLayout->setSpacing(6);
|
2015-12-03 21:31:56 +01:00
|
|
|
// TODO add a user defined string attribute to toolbar as toolbar title
|
2015-11-04 22:44:41 +01:00
|
|
|
d->leftToolBox->addItem(toolBar, toolbar.id());
|
|
|
|
|
toolBars.insert(toolbar.id(), toolBar);
|
2015-09-21 12:11:02 +02:00
|
|
|
} else {
|
|
|
|
|
toolBarLayout = toolBar->layout();
|
2017-07-09 11:49:13 +02:00
|
|
|
QMT_ASSERT(toolBarLayout, continue);
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
2015-11-04 22:44:41 +01:00
|
|
|
foreach (const qmt::Toolbar::Tool &tool, toolbar.tools()) {
|
2015-11-03 22:30:46 +01:00
|
|
|
switch (tool.m_toolType) {
|
2015-11-04 23:34:44 +01:00
|
|
|
case qmt::Toolbar::TooltypeTool:
|
2015-09-21 12:11:02 +02:00
|
|
|
{
|
|
|
|
|
QString iconPath;
|
2015-11-04 23:34:44 +01:00
|
|
|
qmt::StereotypeIcon::Element stereotypeIconElement = qmt::StereotypeIcon::ElementAny;
|
|
|
|
|
qmt::StyleEngine::ElementType styleEngineElementType = qmt::StyleEngine::TypeOther;
|
2015-11-03 22:30:46 +01:00
|
|
|
if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_PACKAGE)) {
|
2017-07-30 21:38:49 +02:00
|
|
|
iconPath = ":/modelinglib/48x48/package.png";
|
2015-11-04 23:34:44 +01:00
|
|
|
stereotypeIconElement = qmt::StereotypeIcon::ElementPackage;
|
|
|
|
|
styleEngineElementType = qmt::StyleEngine::TypePackage;
|
2015-11-03 22:30:46 +01:00
|
|
|
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_COMPONENT)) {
|
2017-07-30 21:38:49 +02:00
|
|
|
iconPath = ":/modelinglib/48x48/component.png";
|
2015-11-04 23:34:44 +01:00
|
|
|
stereotypeIconElement = qmt::StereotypeIcon::ElementComponent;
|
|
|
|
|
styleEngineElementType = qmt::StyleEngine::TypeComponent;
|
2015-11-03 22:30:46 +01:00
|
|
|
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_CLASS)) {
|
2017-07-30 21:38:49 +02:00
|
|
|
iconPath = ":/modelinglib/48x48/class.png";
|
2015-11-04 23:34:44 +01:00
|
|
|
stereotypeIconElement = qmt::StereotypeIcon::ElementClass;
|
|
|
|
|
styleEngineElementType = qmt::StyleEngine::TypeClass;
|
2015-11-03 22:30:46 +01:00
|
|
|
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_ITEM)) {
|
2017-07-30 21:38:49 +02:00
|
|
|
iconPath = ":/modelinglib/48x48/item.png";
|
2015-11-04 23:34:44 +01:00
|
|
|
stereotypeIconElement = qmt::StereotypeIcon::ElementItem;
|
|
|
|
|
styleEngineElementType = qmt::StyleEngine::TypeItem;
|
2015-11-03 22:30:46 +01:00
|
|
|
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_ANNOTATION)) {
|
2017-07-30 21:38:49 +02:00
|
|
|
iconPath = ":/modelinglib/48x48/annotation.png";
|
2015-11-04 23:34:44 +01:00
|
|
|
styleEngineElementType = qmt::StyleEngine::TypeAnnotation;
|
2015-11-03 22:30:46 +01:00
|
|
|
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_BOUNDARY)) {
|
2017-07-30 21:38:49 +02:00
|
|
|
iconPath = ":/modelinglib/48x48/boundary.png";
|
2015-11-04 23:34:44 +01:00
|
|
|
styleEngineElementType = qmt::StyleEngine::TypeBoundary;
|
2017-07-15 15:37:19 +02:00
|
|
|
} else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_SWIMLANE)) {
|
2017-07-30 21:38:49 +02:00
|
|
|
iconPath = ":/modelinglib/48x48/swimlane.png";
|
2017-07-15 15:37:19 +02:00
|
|
|
styleEngineElementType = qmt::StyleEngine::TypeSwimlane;
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
QIcon icon;
|
2017-08-02 09:44:21 +02:00
|
|
|
QString newElementName = tr("New %1").arg(tool.m_name);
|
2015-11-04 23:34:44 +01:00
|
|
|
if (!tool.m_stereotype.isEmpty() && stereotypeIconElement != qmt::StereotypeIcon::ElementAny) {
|
2015-11-04 22:44:41 +01:00
|
|
|
const qmt::Style *style = documentController->styleController()->adaptStyle(styleEngineElementType);
|
2015-09-21 12:11:02 +02:00
|
|
|
icon = stereotypeController->createIcon(
|
2020-04-29 09:49:40 +02:00
|
|
|
stereotypeIconElement, {tool.m_stereotype},
|
2018-01-03 18:37:20 +01:00
|
|
|
QString(), style, QSize(128, 128), QMarginsF(6.0, 4.0, 6.0, 8.0), 8.0);
|
2017-08-02 09:44:21 +02:00
|
|
|
if (!icon.isNull()) {
|
|
|
|
|
QString stereotypeIconId = stereotypeController->findStereotypeIconId(
|
2020-04-29 09:49:40 +02:00
|
|
|
stereotypeIconElement, {tool.m_stereotype});
|
2017-08-02 09:44:21 +02:00
|
|
|
qmt::StereotypeIcon stereotypeIcon = stereotypeController->findStereotypeIcon(stereotypeIconId);
|
|
|
|
|
if (stereotypeIcon.hasName())
|
|
|
|
|
newElementName = stereotypeIcon.name();
|
|
|
|
|
}
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
if (icon.isNull())
|
|
|
|
|
icon = QIcon(iconPath);
|
|
|
|
|
if (!icon.isNull()) {
|
2017-08-02 09:44:21 +02:00
|
|
|
toolBarLayout->addWidget(new DragTool(icon, tool.m_name, newElementName, tool.m_elementType,
|
2015-11-03 22:30:46 +01:00
|
|
|
tool.m_stereotype, toolBar));
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-11-04 23:34:44 +01:00
|
|
|
case qmt::Toolbar::TooltypeSeparator:
|
2015-09-21 12:11:02 +02:00
|
|
|
{
|
|
|
|
|
auto horizLine1 = new QFrame(d->leftToolBox);
|
|
|
|
|
horizLine1->setFrameShape(QFrame::HLine);
|
|
|
|
|
toolBarLayout->addWidget(horizLine1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fallback if no toolbar was defined
|
|
|
|
|
if (!toolBars.isEmpty()) {
|
2017-07-30 21:38:49 +02:00
|
|
|
QString generalId = "General";
|
2015-09-21 12:11:02 +02:00
|
|
|
auto toolBar = new QWidget(d->leftToolBox);
|
2015-12-03 21:31:56 +01:00
|
|
|
toolBar->setProperty(PROPERTYNAME_TOOLBARID, generalId);
|
2015-09-21 12:11:02 +02:00
|
|
|
auto toolBarLayout = new QVBoxLayout(toolBar);
|
|
|
|
|
toolBarLayout->setContentsMargins(2, 2, 2, 2);
|
|
|
|
|
toolBarLayout->setSpacing(6);
|
|
|
|
|
d->leftToolBox->insertItem(0, toolBar, generalId);
|
|
|
|
|
toolBars.insert(generalId, toolBar);
|
|
|
|
|
toolBarLayout->addWidget(
|
2017-07-30 21:38:49 +02:00
|
|
|
new DragTool(QIcon(":/modelinglib/48x48/package.png"),
|
2017-08-02 09:44:21 +02:00
|
|
|
tr("Package"), tr("New Package"), QLatin1String(qmt::ELEMENT_TYPE_PACKAGE),
|
2015-09-21 12:11:02 +02:00
|
|
|
QString(), toolBar));
|
|
|
|
|
toolBarLayout->addWidget(
|
2017-07-30 21:38:49 +02:00
|
|
|
new DragTool(QIcon(":/modelinglib/48x48/component.png"),
|
2017-08-02 09:44:21 +02:00
|
|
|
tr("Component"), tr("New Component"), QLatin1String(qmt::ELEMENT_TYPE_COMPONENT),
|
2015-09-21 12:11:02 +02:00
|
|
|
QString(), toolBar));
|
|
|
|
|
toolBarLayout->addWidget(
|
2017-07-30 21:38:49 +02:00
|
|
|
new DragTool(QIcon(":/modelinglib/48x48/class.png"),
|
2017-08-02 09:44:21 +02:00
|
|
|
tr("Class"), tr("New Class"), QLatin1String(qmt::ELEMENT_TYPE_CLASS),
|
2015-09-21 12:11:02 +02:00
|
|
|
QString(), toolBar));
|
|
|
|
|
toolBarLayout->addWidget(
|
2017-07-30 21:38:49 +02:00
|
|
|
new DragTool(QIcon(":/modelinglib/48x48/item.png"),
|
2017-08-02 09:44:21 +02:00
|
|
|
tr("Item"), tr("New Item"), QLatin1String(qmt::ELEMENT_TYPE_ITEM),
|
2015-09-21 12:11:02 +02:00
|
|
|
QString(), toolBar));
|
|
|
|
|
auto horizLine1 = new QFrame(d->leftToolBox);
|
|
|
|
|
horizLine1->setFrameShape(QFrame::HLine);
|
|
|
|
|
toolBarLayout->addWidget(horizLine1);
|
|
|
|
|
toolBarLayout->addWidget(
|
2017-07-30 21:38:49 +02:00
|
|
|
new DragTool(QIcon(":/modelinglib/48x48/annotation.png"),
|
2017-08-02 09:44:21 +02:00
|
|
|
tr("Annotation"), QString(), QLatin1String(qmt::ELEMENT_TYPE_ANNOTATION),
|
2015-09-21 12:11:02 +02:00
|
|
|
QString(), toolBar));
|
|
|
|
|
toolBarLayout->addWidget(
|
2017-07-30 21:38:49 +02:00
|
|
|
new DragTool(QIcon(":/modelinglib/48x48/boundary.png"),
|
2017-08-02 09:44:21 +02:00
|
|
|
tr("Boundary"), QString(), QLatin1String(qmt::ELEMENT_TYPE_BOUNDARY),
|
2015-09-21 12:11:02 +02:00
|
|
|
QString(), toolBar));
|
2017-07-15 15:37:19 +02:00
|
|
|
toolBarLayout->addWidget(
|
2017-07-30 21:38:49 +02:00
|
|
|
new DragTool(QIcon(":/modelinglib/48x48/swimlane.png"),
|
2017-08-02 09:44:21 +02:00
|
|
|
tr("Swimlane"), QString(), QLatin1String(qmt::ELEMENT_TYPE_SWIMLANE),
|
2017-07-15 15:37:19 +02:00
|
|
|
QString(), toolBar));
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add stretch to all layouts and calculate width of tool bar
|
|
|
|
|
int maxWidth = 48;
|
|
|
|
|
foreach (QWidget *toolBar, toolBars) {
|
2017-07-09 11:49:13 +02:00
|
|
|
QMT_ASSERT(toolBar, continue);
|
2015-09-21 12:11:02 +02:00
|
|
|
auto layout = qobject_cast<QBoxLayout *>(toolBar->layout());
|
2017-07-09 11:49:13 +02:00
|
|
|
QMT_ASSERT(layout, continue);
|
2015-09-21 12:11:02 +02:00
|
|
|
layout->addStretch(1);
|
|
|
|
|
toolBar->adjustSize();
|
|
|
|
|
if (maxWidth < toolBar->width())
|
|
|
|
|
maxWidth = toolBar->width();
|
|
|
|
|
}
|
|
|
|
|
d->leftToolBox->setFixedWidth(maxWidth);
|
|
|
|
|
|
|
|
|
|
d->leftToolBox->setCurrentIndex(0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 15:25:23 +02:00
|
|
|
void ModelEditor::openDiagram(qmt::MDiagram *diagram, bool addToHistory)
|
|
|
|
|
{
|
|
|
|
|
closeCurrentDiagram(addToHistory);
|
|
|
|
|
if (diagram) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::DiagramSceneModel *diagramSceneModel = d->document->documentController()->diagramsManager()->bindDiagramSceneModel(diagram);
|
2015-09-25 15:25:23 +02:00
|
|
|
d->diagramView->setDiagramSceneModel(diagramSceneModel);
|
|
|
|
|
d->diagramStack->setCurrentWidget(d->diagramView);
|
|
|
|
|
updateSelectedArea(SelectedArea::Nothing);
|
|
|
|
|
addDiagramToSelector(diagram);
|
2015-12-03 21:31:56 +01:00
|
|
|
if (!diagram->toolbarId().isEmpty()) {
|
|
|
|
|
for (int i = 0; i < d->leftToolBox->count(); ++i) {
|
|
|
|
|
QWidget *widget = d->leftToolBox->widget(i);
|
|
|
|
|
if (widget && widget->property(PROPERTYNAME_TOOLBARID).toString() == diagram->toolbarId()) {
|
|
|
|
|
d->leftToolBox->setCurrentIndex(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
storeToolbarIdInDiagram(diagram);
|
|
|
|
|
}
|
2015-09-25 15:25:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::closeCurrentDiagram(bool addToHistory)
|
2015-09-21 12:11:02 +02:00
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::DiagramsManager *diagramsManager = documentController->diagramsManager();
|
|
|
|
|
qmt::DiagramSceneModel *sceneModel = d->diagramView->diagramSceneModel();
|
2015-09-21 12:11:02 +02:00
|
|
|
if (sceneModel) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MDiagram *diagram = sceneModel->diagram();
|
2015-09-21 12:11:02 +02:00
|
|
|
if (diagram) {
|
2015-09-25 15:25:23 +02:00
|
|
|
if (addToHistory)
|
|
|
|
|
addToNavigationHistory(diagram);
|
2015-09-21 12:11:02 +02:00
|
|
|
d->diagramStack->setCurrentWidget(d->noDiagramLabel);
|
2019-07-31 17:21:41 +02:00
|
|
|
d->diagramView->setDiagramSceneModel(nullptr);
|
2015-09-21 12:11:02 +02:00
|
|
|
diagramsManager->unbindDiagramSceneModel(diagram);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::closeDiagram(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::DiagramsManager *diagramsManager = documentController->diagramsManager();
|
|
|
|
|
qmt::DiagramSceneModel *sceneModel = d->diagramView->diagramSceneModel();
|
|
|
|
|
if (sceneModel && diagram == sceneModel->diagram()) {
|
2015-09-25 15:25:23 +02:00
|
|
|
addToNavigationHistory(diagram);
|
2015-09-21 12:11:02 +02:00
|
|
|
d->diagramStack->setCurrentWidget(d->noDiagramLabel);
|
2019-07-31 17:21:41 +02:00
|
|
|
d->diagramView->setDiagramSceneModel(nullptr);
|
2015-09-21 12:11:02 +02:00
|
|
|
diagramsManager->unbindDiagramSceneModel(diagram);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::closeAllDiagrams()
|
|
|
|
|
{
|
2015-09-25 15:25:23 +02:00
|
|
|
closeCurrentDiagram(true);
|
2015-09-21 12:11:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-31 18:06:36 +02:00
|
|
|
void ModelEditor::onContentSet()
|
|
|
|
|
{
|
2015-09-21 12:11:02 +02:00
|
|
|
initDocument();
|
2015-08-31 18:06:36 +02:00
|
|
|
|
|
|
|
|
// open diagram
|
2015-09-21 12:11:02 +02:00
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
qmt::MDiagram *rootDiagram = documentController->findOrCreateRootDiagram();
|
2015-08-31 18:06:36 +02:00
|
|
|
showDiagram(rootDiagram);
|
2015-09-21 12:11:02 +02:00
|
|
|
// select diagram in model tree view
|
2015-11-13 09:31:39 +01:00
|
|
|
QModelIndex modelIndex = documentController->treeModel()->indexOf(rootDiagram);
|
2015-09-21 12:11:02 +02:00
|
|
|
if (modelIndex.isValid())
|
|
|
|
|
d->modelTreeView->selectFromSourceModelIndex(modelIndex);
|
2015-08-31 18:06:36 +02:00
|
|
|
|
|
|
|
|
expandModelTreeToDepth(0);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-07 20:31:02 +01:00
|
|
|
void ModelEditor::setDiagramClipboard(const qmt::DContainer &dcontainer)
|
|
|
|
|
{
|
|
|
|
|
ExtDocumentController *documentController = d->document->documentController();
|
|
|
|
|
qmt::ModelController *modelController = documentController->modelController();
|
|
|
|
|
qmt::MSelection modelSelection;
|
|
|
|
|
for (const auto &delement : dcontainer.elements()) {
|
|
|
|
|
qmt::Uid melementUid = delement->modelUid();
|
|
|
|
|
qmt::Uid mownerUid = modelController->ownerKey(melementUid);
|
|
|
|
|
modelSelection.append(melementUid, mownerUid);
|
|
|
|
|
}
|
|
|
|
|
qmt::MContainer mcontainer = modelController->copyElements(modelSelection);
|
|
|
|
|
ModelEditorPlugin::modelsManager()->setDiagramClipboard(documentController, dcontainer, mcontainer);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 09:47:34 +02:00
|
|
|
void ModelEditor::addDiagramToSelector(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
|
|
|
|
QString diagramLabel = buildDiagramLabel(diagram);
|
2015-11-04 22:44:41 +01:00
|
|
|
QVariant diagramUid = QVariant::fromValue(diagram->uid());
|
2015-09-25 09:47:34 +02:00
|
|
|
int i = d->diagramSelector->findData(diagramUid);
|
|
|
|
|
if (i >= 0)
|
|
|
|
|
d->diagramSelector->removeItem(i);
|
2017-07-30 21:38:49 +02:00
|
|
|
d->diagramSelector->insertItem(0, QIcon(":/modelinglib/48x48/canvas-diagram.png"), diagramLabel, diagramUid);
|
2015-09-25 09:47:34 +02:00
|
|
|
d->diagramSelector->setCurrentIndex(0);
|
|
|
|
|
while (d->diagramSelector->count() > 20)
|
|
|
|
|
d->diagramSelector->removeItem(d->diagramSelector->count() - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::updateDiagramSelector()
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (i < d->diagramSelector->count()) {
|
|
|
|
|
qmt::Uid diagramUid = d->diagramSelector->itemData(i).value<qmt::Uid>();
|
|
|
|
|
if (diagramUid.isValid()) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MDiagram *diagram = d->document->documentController()->modelController()->findObject<qmt::MDiagram>(diagramUid);
|
2015-09-25 09:47:34 +02:00
|
|
|
if (diagram) {
|
|
|
|
|
QString diagramLabel = buildDiagramLabel(diagram);
|
|
|
|
|
if (diagramLabel != d->diagramSelector->itemText(i))
|
|
|
|
|
d->diagramSelector->setItemText(i, diagramLabel);
|
|
|
|
|
++i;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
d->diagramSelector->removeItem(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::onDiagramSelectorSelected(int index)
|
|
|
|
|
{
|
|
|
|
|
qmt::Uid diagramUid = d->diagramSelector->itemData(index).value<qmt::Uid>();
|
|
|
|
|
if (diagramUid.isValid()) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MDiagram *diagram = d->document->documentController()->modelController()->findObject<qmt::MDiagram>(diagramUid);
|
2015-09-25 09:47:34 +02:00
|
|
|
if (diagram) {
|
|
|
|
|
showDiagram(diagram);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
d->diagramSelector->setCurrentIndex(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString ModelEditor::buildDiagramLabel(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
2015-11-04 22:44:41 +01:00
|
|
|
QString label = diagram->name();
|
|
|
|
|
qmt::MObject *owner = diagram->owner();
|
2015-09-25 09:47:34 +02:00
|
|
|
QStringList path;
|
|
|
|
|
while (owner) {
|
2015-11-04 22:44:41 +01:00
|
|
|
path.append(owner->name());
|
|
|
|
|
owner = owner->owner();
|
2015-09-25 09:47:34 +02:00
|
|
|
}
|
|
|
|
|
if (!path.isEmpty()) {
|
2017-07-30 21:38:49 +02:00
|
|
|
label += " [";
|
2015-09-25 09:47:34 +02:00
|
|
|
label += path.last();
|
|
|
|
|
for (int i = path.count() - 2; i >= 0; --i) {
|
|
|
|
|
label += QLatin1Char('.');
|
|
|
|
|
label += path.at(i);
|
|
|
|
|
}
|
|
|
|
|
label += QLatin1Char(']');
|
|
|
|
|
}
|
|
|
|
|
return label;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-03 21:31:56 +01:00
|
|
|
void ModelEditor::storeToolbarIdInDiagram(qmt::MDiagram *diagram)
|
|
|
|
|
{
|
|
|
|
|
int leftToolboxIndex = d->leftToolBox->currentIndex();
|
|
|
|
|
if (diagram && leftToolboxIndex >= 0 && leftToolboxIndex < d->leftToolBox->count()) {
|
|
|
|
|
QWidget *widget = d->leftToolBox->widget(leftToolboxIndex);
|
|
|
|
|
if (widget) {
|
|
|
|
|
QString toolbarId = widget->property(PROPERTYNAME_TOOLBARID).toString();
|
|
|
|
|
if (toolbarId != diagram->toolbarId()) {
|
|
|
|
|
// NOTE: This update is done without calling ModelController::startUpdateObject() by intention.
|
|
|
|
|
// This update does not need to be seen by any other controller nor shall it
|
|
|
|
|
// No undo shall be possible
|
|
|
|
|
// The document should not be set to modified state
|
|
|
|
|
diagram->setToolbarId(toolbarId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 15:25:23 +02:00
|
|
|
void ModelEditor::addToNavigationHistory(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
2016-05-14 22:26:26 +03:00
|
|
|
if (Core::EditorManager::currentEditor() == this) {
|
2015-09-25 15:25:23 +02:00
|
|
|
Core::EditorManager::cutForwardNavigationHistory();
|
|
|
|
|
Core::EditorManager::addCurrentPositionToNavigationHistory(saveState(diagram));
|
2016-05-14 22:26:26 +03:00
|
|
|
}
|
2015-09-25 15:25:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray ModelEditor::saveState(const qmt::MDiagram *diagram) const
|
|
|
|
|
{
|
|
|
|
|
QByteArray state;
|
|
|
|
|
QDataStream stream(&state, QIODevice::WriteOnly);
|
2016-06-24 18:53:54 +02:00
|
|
|
stream << 2; // version number
|
2015-09-25 15:25:23 +02:00
|
|
|
if (diagram)
|
2015-11-04 22:44:41 +01:00
|
|
|
stream << diagram->uid();
|
2015-09-25 15:25:23 +02:00
|
|
|
else
|
2015-11-04 22:44:41 +01:00
|
|
|
stream << qmt::Uid::invalidUid();
|
2016-06-24 18:53:54 +02:00
|
|
|
stream << d->actionHandler->synchronizeBrowserAction()->isChecked()
|
|
|
|
|
<< d->syncBrowserWithDiagramAction->isChecked()
|
|
|
|
|
<< d->syncDiagramWithBrowserAction->isChecked()
|
|
|
|
|
<< d->syncEachOtherAction->isChecked();
|
2015-09-25 15:25:23 +02:00
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-25 09:47:34 +02:00
|
|
|
void ModelEditor::onEditSelectedElement()
|
|
|
|
|
{
|
|
|
|
|
// TODO introduce similar method for selected elements in model tree
|
|
|
|
|
// currently this method is called on adding new elements in model tree
|
|
|
|
|
// but the method is a no-op in that case.
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::MDiagram *diagram = d->propertiesView->selectedDiagram();
|
|
|
|
|
QList<qmt::DElement *> elements = d->propertiesView->selectedDiagramElements();
|
2015-09-25 09:47:34 +02:00
|
|
|
if (diagram && !elements.isEmpty()) {
|
|
|
|
|
qmt::DElement *element = elements.at(0);
|
|
|
|
|
if (element) {
|
2015-11-04 22:44:41 +01:00
|
|
|
qmt::DiagramSceneModel *diagramSceneModel = d->document->documentController()->diagramsManager()->diagramSceneModel(diagram);
|
2015-09-25 09:47:34 +02:00
|
|
|
if (diagramSceneModel->isElementEditable(element)) {
|
2015-12-27 16:19:33 +01:00
|
|
|
d->diagramStack->currentWidget()->setFocus();
|
2015-09-25 09:47:34 +02:00
|
|
|
diagramSceneModel->editElement(element);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
d->propertiesView->editSelectedElement();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-24 18:53:54 +02:00
|
|
|
bool ModelEditor::isSyncBrowserWithDiagram() const
|
|
|
|
|
{
|
|
|
|
|
return d->actionHandler->synchronizeBrowserAction()->isChecked()
|
|
|
|
|
&& (d->syncBrowserWithDiagramAction->isChecked() || d->syncEachOtherAction->isChecked());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ModelEditor::isSyncDiagramWithBrowser() const
|
|
|
|
|
{
|
|
|
|
|
return d->actionHandler->synchronizeBrowserAction()->isChecked()
|
|
|
|
|
&& (d->syncDiagramWithBrowserAction->isChecked() || d->syncEachOtherAction->isChecked());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::synchronizeDiagramWithBrowser()
|
|
|
|
|
{
|
|
|
|
|
if (isSyncDiagramWithBrowser()) {
|
|
|
|
|
if (currentDiagram()) {
|
|
|
|
|
bool done = false;
|
|
|
|
|
qmt::DocumentController *documentController = d->document->documentController();
|
|
|
|
|
QModelIndexList indexes = d->modelTreeView->selectedSourceModelIndexes();
|
|
|
|
|
if (!indexes.isEmpty()) {
|
|
|
|
|
foreach (const QModelIndex &index, indexes) {
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
qmt::MElement *modelElement = documentController->treeModel()->element(index);
|
|
|
|
|
if (modelElement) {
|
|
|
|
|
foreach (qmt::DElement *diagramElement, currentDiagram()->diagramElements()) {
|
|
|
|
|
if (diagramElement->modelUid() == modelElement->uid()) {
|
|
|
|
|
// disconnect temporarily avoiding double update of properties Ui
|
|
|
|
|
disconnect(documentController->diagramsManager(), &qmt::DiagramsManager::diagramSelectionChanged,
|
|
|
|
|
this, &ModelEditor::onDiagramSelectionChanged);
|
|
|
|
|
d->diagramView->diagramSceneModel()->selectElement(diagramElement);
|
2018-08-09 15:02:29 +02:00
|
|
|
QGraphicsItem *item = d->diagramView->diagramSceneModel()->graphicsItem(diagramElement);
|
|
|
|
|
if (item)
|
|
|
|
|
d->diagramView->ensureVisible(item);
|
2016-06-24 18:53:54 +02:00
|
|
|
connect(documentController->diagramsManager(), &qmt::DiagramsManager::diagramSelectionChanged,
|
|
|
|
|
this, &ModelEditor::onDiagramSelectionChanged, Qt::QueuedConnection);
|
|
|
|
|
done = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (done)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelEditor::synchronizeBrowserWithDiagram(const qmt::MDiagram *diagram)
|
|
|
|
|
{
|
|
|
|
|
if (isSyncBrowserWithDiagram()) {
|
|
|
|
|
qmt::DocumentController *documentController = d->document->documentController();
|
|
|
|
|
qmt::DSelection selection = documentController->diagramsManager()->diagramSceneModel(diagram)->selectedElements();
|
|
|
|
|
if (!selection.isEmpty()) {
|
|
|
|
|
foreach (qmt::DSelection::Index index, selection.indices()) {
|
|
|
|
|
qmt::DElement *diagramElement = documentController->diagramController()->findElement(index.elementKey(), diagram);
|
|
|
|
|
if (diagramElement) {
|
|
|
|
|
qmt::MElement *modelElement = documentController->modelController()->findElement(diagramElement->modelUid());
|
|
|
|
|
if (modelElement) {
|
|
|
|
|
QModelIndex index = d->modelTreeViewServant->treeModel()->indexOf(modelElement);
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
// disconnect temporarily avoiding double update of properties Ui
|
|
|
|
|
disconnect(d->modelTreeView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
|
|
|
this, &ModelEditor::onTreeViewSelectionChanged);
|
|
|
|
|
d->modelTreeView->selectFromSourceModelIndex(index);
|
|
|
|
|
connect(d->modelTreeView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
|
|
|
this, &ModelEditor::onTreeViewSelectionChanged, Qt::QueuedConnection);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-31 18:06:36 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace ModelEditor
|