Commit d92142f1 authored by Jochen Becher's avatar Jochen Becher

Add new ModelEditor plugin.

The plugin is based on the 'modelinglib' library. For features and
screenshots see https://wiki.qt.io/ModelEditor

Change-Id: I857be0652a852cc69a9729f64e67134fe630af00
Reviewed-by: default avatarTobias Hunger <tobias.hunger@theqtcompany.com>
parent 64e2ba87
// ModelEditor - definitions of custom shapes
//
// Language syntax and commands:
//
// Icon <name>
// Title: <a UI title. Defaults to the name of the icon.>
// Elements: <comma-separated list of element types the
// definiton applies to: class, component, package, diagram, item.
// Default applies definition to all element types.>
// Stereotype: <stereotype as a string.>
// Display: <default display of element.
// One of: none, label, decoration, icon, smart.
// Default is smart.>
// Width: <width of icon in pixels. The width defines the width of the icon as decoration.>
// Height: <height of icon in pixels. The height defines the height of the icon as decoration.>
// MinWidth: <minimum width of custom icon in pixels.>
// MinHeight: <minimum height of custom icon in pixels.>
// LockSize: <lock resizing.
// One of: none, width, height, size, ratio.
// Default is none.>
// TextAlignment: <alignment of text.
// One of: top, center, below.
// Defaults to center.>
// BaseColor: <color #rrggbb>
// Begin
// Line <x1>, <y1>, <x2>, <y2>
// Rect <x>, <y>, <width>, <height>
// RoundedRect <x>, <y>, <width>, <height>, <radius>
// Circle <center_x>, <center_y>, <radius>
// Ellipse <center_x>, <center_y>, <radius_x>, <radius_y>
// Arc <center_x>, <center_y>, <radius_x>, <radius_y>, <start_angle>, <span_angle>
// MoveTo <x>, <y>
// LineTo <x>, <y>
// ArcMoveTo <center_x>, <center_y>, <radius_x>, <radius_y>, <angle>
// ArcTo <center_x>, <center_y>, <radius_x>, <radius_y>, <angle>, <span_angle>
// Close
// End
//
// Toolbar <name>
// Priority: <priority which decides about the position of toolbar in toolbox>
// Begin
// Tool <title>, <element type>[, <stereotype>]
// Separator
// End
//
// *************
// ** Classes **
// *************
Icon Interface
Elements: class
Stereotype: 'interface'
Display: icon
Width: 20.0
Height: 20.0
LockSize: ratio
Begin
Circle 10.0, 10.0, 10.0
End
Icon Boundary
Stereotype: 'boundary'
Width: 24.0
Height: 20.0
LockSize: ratio
Begin
Circle 14.0, 10.0, 10.0
Line 0.0, 0.0, 0.0, 20.0
Line 0.0, 10.0, 4.0, 10.0
End
Icon Control
Stereotype: 'control'
Width: 20.0
Height: 20.0
LockSize: ratio
Begin
Circle 10.0, 10.0, 10.0
Line 10.0, 0.0, 14.0, -2.0
Line 10.0, 0.0, 14.0, 4.0
End
Icon Entity
Stereotype: 'entity'
Width: 20.0
Height: 20.0
LockSize: ratio
Begin
Circle 10.0, 10.0, 10.0
Line 0.0, 20.0, 20.0, 20.0
End
// ****************
// ** Components **
// ****************
Icon Database
Stereotype: 'database'
Display: icon
Width: 20.0
Height: 20.0
Begin
MoveTo 0.0, 3.0
LineTo 0.0, 17.0
ArcTo 10.0, 17.0, 10.0, 3.0, 180.0, 180.0
LineTo 20.0, 3.0
ArcTo 10.0, 3.0, 10.0, 3.0, 0.0, -180.0
Close
Arc 10.0, 3.0, 10.0, 3.0, 0.0, 180.0
End
// experimental replacement of default shape with custom shape
Icon Component
Elements: component, package, diagram
Stereotype: 'component'
Display: decoration
Width: 20.0
Height: 16.0
TextAlignment: center
Begin
Rect 0, 0, 20.0, 16.0
Rect -4.0, 2.5, 8, 4
Rect -4.0, 9.5, 8, 4
End
// ***************
// ** Use Cases **
// ***************
Icon UseCase
Title: "Use-Case"
Elements: item
Stereotype: 'usecase'
Display: icon
Width: 40
Height: 20
BaseColor: #5fb4f0
Begin
Ellipse 20, 10, 20, 10
End
Icon Actor
Elements: item
Stereotype: 'actor'
Display: icon
Width: 20
Height: 40
LockSize: ratio
BaseColor: #5fb4f0
Begin
Circle 10, 5, 5
Line 0, 15, 20, 15
Line 10, 10, 10, 25
Line 10, 25, 3, 40
Line 10, 25, 17, 40
End
// ****************
// ** Activities **
// ****************
Icon Start
Elements: item
Stereotype: 'start'
Display: icon
Width: 20
Height: 20
LockSize: ratio
BaseColor: #81d657
Begin
Circle 10, 10, 7
End
Icon Activity
Elements: item
Stereotype: 'activity'
Display: icon
Width: 40
Height: 20
BaseColor: #81d657
Begin
RoundedRect 0, 0, 40, 20, 10
End
Icon Condition
Elements: item
Stereotype: 'condition'
Display: icon
Width: 20
Height: 20
LockSize: ratio
BaseColor: #81d657
Begin
MoveTo 10, 0
LineTo 20, 10
LineTo 10, 20
LineTo 0, 10
Close
End
Icon HorizontalBar
Title: "Horizontal Bar"
Elements: item
Stereotype: 'horizontalbar'
Display: icon
Width: 20
Height: 5
MinWidth: 20
MinHeight: 5
LockSize: height
BaseColor: #000000
Begin
RoundedRect 0, 0, 20, 5, 1
End
Icon VerticalBar
Title: "Vertical Bar"
Elements: item
Stereotype: 'verticalbar'
Display: icon
Width: 5
Height: 20
MinWidth: 5
MinHeight: 20
LockSize: width
BaseColor: #000000
Begin
RoundedRect 0, 0, 5, 20, 1
End
Icon Termination
Elements: item
Stereotype: 'termination'
Display: icon
Width: 20
Height: 20
LockSize: ratio
BaseColor: #81d657
Begin
Circle 10, 10, 10
Circle 10, 10, 7
End
// **************
// ** Toolbars **
// **************
Toolbar Classes
Begin
Tool "Package", package
Tool "Class", class
Tool "Interface", class, "interface"
Tool "Control", class, "control"
Tool "Entity", class, "entity"
Tool "Boundary", class, "boundary"
Separator
Tool "Annotation", annotation
Tool "Boundary", boundary
End
Toolbar Components
Begin
Tool "Package", package
Tool "Component", component
Tool "Database", component, "database"
Separator
Tool "Annotation", annotation
Tool "Boundary", boundary
End
Toolbar UseCases
Begin
Tool "Package", package
Tool "UseCase", item, "usecase"
Tool "Actor", item, "actor"
Separator
Tool "Annotation", annotation
Tool "Boundary", boundary
End
Toolbar Activities
Begin
Tool "Start", item, "start"
Tool "Activity", item, "activity"
Tool "Condition", item, "condition"
Tool "Horiz. Bar", item, "horizontalbar"
Tool "Vert. Bar", item, "verticalbar"
Tool "Termination", item, "termination"
Separator
Tool "Annotation", annotation
Tool "Boundary", boundary
End
......@@ -39,6 +39,7 @@ DATA_DIRS = \
qmlicons \
qml \
qml-type-descriptions \
modeleditor \
generic-highlighter \
glsl \
cplusplus
......
......@@ -15,6 +15,7 @@ Product {
"designer/**/*",
"generic-highlighter/**/*",
"glsl/**/*",
"modeleditor/**/*",
"qml/**/*",
"qmldesigner/**/*",
"qmlicons/**/*",
......
{
\"Name\" : \"ModelEditor\",
\"Version\" : \"$$QTCREATOR_VERSION\",
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
\"Vendor\" : \"Jochen Becher\",
\"Copyright\" : \"(C) 2014,2015 Jochen Becher\",
\"License\" : [ \"Commercial Usage\",
\"\",
\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\",
\"\",
\"GNU Lesser General Public License Usage\",
\"\",
\"Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 or version 3 as published by the Free Software Foundation. Please review the following information to ensure the GNU Lesser General Public License requirements will be met: https://www.gnu.org/licenses/lgpl.html and http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\"
],
\"Category\" : \"Modeling\",
\"Description\" : \"Graphical modeling with structured diagrams.\",
\"Url\" : \"http://www.qt.io\",
\"Experimental\" : true,
$$dependencyList
}
This diff is collapsed.
/***************************************************************************
**
** Copyright (C) 2015 Jochen Becher
** Contact: http://www.qt.io/licensing
**
** 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
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef ABSTRACTEDITOR_H
#define ABSTRACTEDITOR_H
#include <coreplugin/editormanager/ieditor.h>
#include <QAbstractButton>
#include <functional>
QT_BEGIN_NAMESPACE
class QItemSelection;
QT_END_NAMESPACE
namespace qmt {
class MElement;
class MPackage;
class MDiagram;
class DElement;
class DocumentController;
}
namespace ModelEditor {
namespace Internal {
class UiController;
class ActionHandler;
class DiagramsViewManager;
class DocumentInterface;
enum SelectedArea {
NOTHING_SELECTED,
DIAGRAM_SELECTED,
TREE_VIEW_SELECTED
};
class AbstractEditor :
public Core::IEditor
{
Q_OBJECT
class AbstractEditorPrivate;
public:
explicit AbstractEditor(UiController *uiController, ActionHandler *actionHandler,
QWidget *parent = 0);
~AbstractEditor();
protected:
void init(QWidget *parent);
void setDocument(DocumentInterface *document);
public:
QWidget *toolBar() override;
qmt::MDiagram *editorDiagram() const;
void undo();
void redo();
void cut();
void copy();
void paste();
void removeSelectedElements();
void deleteSelectedElements();
void selectAll();
void editProperties();
qmt::MPackage *guessSelectedPackage() const;
protected:
void updateSelectedArea(SelectedArea selectedArea);
void showProperties(const QList<qmt::MElement *> &modelElements);
void showProperties(qmt::MDiagram *diagram, const QList<qmt::DElement *> &diagramElements);
void clearProperties();
void openDiagram(qmt::MDiagram *diagram);
void showDiagram(qmt::MDiagram *diagram);
void expandModelTreeToDepth(int depth);
QWidget *createToolbarCommandButton(const Core::Id &id, const std::function<void()> &slot,
const QIcon &icon,
const QString &toolTipBase, QWidget *parent);
bool updateButtonIconByTheme(QAbstractButton *button, const QString &name);
private slots:
void onAddPackage();
void onAddComponent();
void onAddClass();
void onAddCanvasDiagram();
void onCurrentEditorChanged(Core::IEditor *editor);
void onCanUndoChanged(bool canUndo);
void onCanRedoChanged(bool canRedo);
void onTreeModelReset();
void onTreeViewSelectionChanged(const QItemSelection &selected,
const QItemSelection &deselected);
void onTreeViewActivated();
void onTreeViewDoubleClicked(const QModelIndex &index);
void onCurrentDiagramChanged(const qmt::MDiagram *diagram);
void onDiagramActivated(const qmt::MDiagram *diagram);
void onDiagramClipboardChanged(bool isEmpty);
void onNewElementCreated(qmt::DElement *element, qmt::MDiagram *diagram);
void onDiagramSelectionChanged(const qmt::MDiagram *diagram);
void onDiagramModified(const qmt::MDiagram *diagram);
void onEditSelectedElement();
void onRightSplitterMoved(int pos, int index);
void onRightSplitterChanged(const QByteArray &state);
void onRightHorizSplitterMoved(int pos, int index);
void onRightHorizSplitterChanged(const QByteArray &state);
private:
void initToolbars();
private:
AbstractEditorPrivate *d;
};
} // namespace Internal
} // namespace ModelEditor
#endif // ABSTRACTEDITOR_H
/***************************************************************************
**
** Copyright (C) 2015 Jochen Becher
** Contact: http://www.qt.io/licensing
**
** 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
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "actionhandler.h"
#include "modeleditor_constants.h"
#include "abstracteditor.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
#include <QAction>
#include <QShortcut>
namespace ModelEditor {
namespace Internal {
class ActionHandler::ActionHandlerPrivate {
public:
Core::Context context;
QAction *undoAction = 0;
QAction *redoAction = 0;
QAction *cutAction = 0;
QAction *copyAction = 0;
QAction *pasteAction = 0;
QAction *removeAction = 0;
QAction *deleteAction = 0;
QAction *selectAllAction = 0;
};
ActionHandler::ActionHandler(const Core::Context &context, QObject *parent)
: QObject(parent),
d(new ActionHandlerPrivate)
{
d->context = context;
}
ActionHandler::~ActionHandler()
{
delete d;
}
QAction *ActionHandler::undoAction() const
{
return d->undoAction;
}
QAction *ActionHandler::redoAction() const
{
return d->redoAction;
}
QAction *ActionHandler::cutAction() const
{
return d->cutAction;
}
QAction *ActionHandler::copyAction() const
{
return d->copyAction;
}
QAction *ActionHandler::pasteAction() const
{
return d->pasteAction;
}
QAction *ActionHandler::removeAction() const
{
return d->removeAction;
}
QAction *ActionHandler::deleteAction() const
{
return d->deleteAction;
}
QAction *ActionHandler::selectAllAction() const
{
return d->selectAllAction;
}
void ActionHandler::createActions()
{
Core::ActionContainer *medit = Core::ActionManager::actionContainer(Core::Constants::M_EDIT);
d->undoAction = registerCommand(Core::Constants::UNDO, [this]() { undo(); })->action();
d->redoAction = registerCommand(Core::Constants::REDO, [this]() { redo(); })->action();
d->cutAction = registerCommand(Core::Constants::CUT, [this]() { cut(); })->action();
d->copyAction = registerCommand(Core::Constants::COPY, [this]() { copy(); })->action();
d->pasteAction = registerCommand(Core::Constants::PASTE, [this]() { paste(); })->action();
Core::Command *removeCommand = registerCommand(
Constants::REMOVE_SELECTED_ELEMENTS, [this]() { removeSelectedElements(); }, true,
tr("&Remove"), QKeySequence::Delete);
medit->addAction(removeCommand, Core::Constants::G_EDIT_COPYPASTE);
d->removeAction = removeCommand->action();
Core::Command *deleteCommand = registerCommand(
Constants::DELETE_SELECTED_ELEMENTS, [this]() { deleteSelectedElements(); }, true,
tr("&Delete"), QKeySequence(QStringLiteral("Ctrl+D")));
medit->addAction(deleteCommand, Core::Constants::G_EDIT_COPYPASTE);
d->deleteAction = deleteCommand->action();
d->selectAllAction = registerCommand(Core::Constants::SELECTALL, [this]() { selectAll(); })->action();
registerCommand(Constants::ACTION_ADD_PACKAGE, 0);
registerCommand(Constants::ACTION_ADD_COMPONENT, 0);
registerCommand(Constants::ACTION_ADD_CLASS, 0);
registerCommand(Constants::ACTION_ADD_CANVAS_DIAGRAM, 0);
}
void ActionHandler::createEditPropertiesShortcut(const Core::Id &shortcutId)
{
auto editAction = new QAction(tr("Edit selected element in properties view"), Core::ICore::mainWindow());
Core::Command *editCommand = Core::ActionManager::registerAction(