Add modeling library

Modeling library implements the entities, diagrams and widget Ui for
ModelEditor plugin and tools. This is a 3rdparty library not following
the QtCreator coding style.

Change-Id: I981e38a10fff1c1792f285d5837553aa7596cd2f
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
Jochen Becher
2015-08-16 13:11:15 +02:00
parent 77661e378a
commit 64e2ba87ef
329 changed files with 48324 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
INCLUDEPATH += $$PWD $$PWD/qtserialization/inc
include(qstringparser/qstringparser.pri)
include(qtserialization/qtserialization.pri)
include(qmt/qmt.pri)

View File

@@ -0,0 +1,112 @@
/***************************************************************************
**
** 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 "configcontroller.h"
#include "stereotypedefinitionparser.h"
#include "textscanner.h"
#include "stringtextsource.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include <QDir>
#include <QFileInfo>
#include <QFile>
#include <QDebug>
namespace qmt {
struct ConfigController::ConfigControllerPrivate
{
ConfigControllerPrivate()
: _stereotype_controller(0)
{
}
StereotypeController *_stereotype_controller;
};
ConfigController::ConfigController(QObject *parent)
: QObject(parent),
d(new ConfigControllerPrivate)
{
}
ConfigController::~ConfigController()
{
delete d;
}
void ConfigController::setStereotypeController(StereotypeController *stereotype_controller)
{
d->_stereotype_controller = stereotype_controller;
}
void ConfigController::readStereotypeDefinitions(const QString &path)
{
StereotypeDefinitionParser parser;
connect(&parser, SIGNAL(iconParsed(StereotypeIcon)), this, SLOT(onStereotypeIconParsed(StereotypeIcon)));
connect(&parser, SIGNAL(toolbarParsed(Toolbar)), this, SLOT(onToolbarParsed(Toolbar)));
QDir dir(path);
dir.setNameFilters(QStringList() << QStringLiteral("*.def"));
foreach (const QString &file_name, dir.entryList(QDir::Files)) {
QFile file(QFileInfo(dir, file_name).absoluteFilePath());
if (file.open(QIODevice::ReadOnly)) {
QString text = QString::fromUtf8(file.readAll());
file.close();
StringTextSource source;
source.setSourceId(1);
source.setText(text);
try {
parser.parse(&source);
} catch (StereotypeDefinitionParserError x) {
qDebug() << x.getErrorMsg() << "in line" << x.getSourcePos().getLineNumber();
} catch (TextScannerError x) {
qDebug() << x.getErrorMsg() << "in line" << x.getSourcePos().getLineNumber();
} catch (...) {
}
}
}
}
void ConfigController::onStereotypeIconParsed(const StereotypeIcon &stereotype_icon)
{
d->_stereotype_controller->addStereotypeIcon(stereotype_icon);
}
void ConfigController::onToolbarParsed(const Toolbar &toolbar)
{
d->_stereotype_controller->addToolbar(toolbar);
}
} // namespace qmt

View File

@@ -0,0 +1,77 @@
/***************************************************************************
**
** 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 QMT_CONFIGCONTROLLER_H
#define QMT_CONFIGCONTROLLER_H
#include <QObject>
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class StereotypeController;
class StereotypeIcon;
class Toolbar;
class QMT_EXPORT ConfigController : public QObject
{
Q_OBJECT
struct ConfigControllerPrivate;
public:
explicit ConfigController(QObject *parent = 0);
~ConfigController();
public:
void setStereotypeController(StereotypeController *stereotype_controller);
public:
void readStereotypeDefinitions(const QString &path);
private slots:
void onStereotypeIconParsed(const StereotypeIcon &stereotype_icon);
void onToolbarParsed(const Toolbar &toolbar);
private:
ConfigControllerPrivate *d;
};
} // namespace qmt
#endif // QMT_CONFIGCONTROLLER_H

View File

@@ -0,0 +1,49 @@
/***************************************************************************
**
** 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 "sourcepos.h"
namespace qmt {
SourcePos::SourcePos()
: _source_id(-1),
_line_number(-1),
_column_number(-1)
{
}
SourcePos::SourcePos(int source_id, int line_number, int column_number)
: _source_id(source_id),
_line_number(line_number),
_column_number(column_number)
{
}
} // namespace qmt

View File

@@ -0,0 +1,66 @@
/***************************************************************************
**
** 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 QMT_SOURCEPOS_H
#define QMT_SOURCEPOS_H
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class QMT_EXPORT SourcePos
{
public:
SourcePos();
SourcePos(int source_id, int line_number, int column_number = -1);
public:
bool isValid() const { return _source_id >= 0 && _line_number >= 0; }
int getSourceId() const { return _source_id; }
int getLineNumber() const { return _line_number; }
bool hasColumnNumber() const { return _column_number >= 0; }
int getColumnNumber() const { return _column_number; }
private:
int _source_id;
int _line_number;
int _column_number;
};
} // namespace qmt
#endif // QMT_SOURCEPOS_H

View File

@@ -0,0 +1,774 @@
/***************************************************************************
**
** 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 "stereotypedefinitionparser.h"
#include "textscanner.h"
#include "token.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/stereotype/stereotypeicon.h"
#include "qmt/stereotype/shapevalue.h"
#include "qmt/stereotype/toolbar.h"
#include <QHash>
#include <QSet>
#include <QPair>
#include <QDebug>
namespace qmt {
// Icon Definition
static const int KEYWORD_ICON = 1;
static const int KEYWORD_TITLE = 2;
static const int KEYWORD_ELEMENTS = 3;
static const int KEYWORD_STEREOTYPE = 4;
static const int KEYWORD_WIDTH = 5;
static const int KEYWORD_HEIGHT = 6;
static const int KEYWORD_MINWIDTH = 7;
static const int KEYWORD_MINHEIGHT = 8;
static const int KEYWORD_LOCK_SIZE = 9;
static const int KEYWORD_DISPLAY = 10;
static const int KEYWORD_TEXTALIGN = 11;
static const int KEYWORD_BASECOLOR = 12;
static const int KEYWORD_BEGIN = 20;
static const int KEYWORD_END = 21;
// Icon Commands
static const int KEYWORD_CIRCLE = 30;
static const int KEYWORD_ELLIPSE = 31;
static const int KEYWORD_LINE = 32;
static const int KEYWORD_RECT = 33;
static const int KEYWORD_ROUNDEDRECT = 34;
static const int KEYWORD_ARC = 35;
static const int KEYWORD_MOVETO = 36;
static const int KEYWORD_LINETO = 37;
static const int KEYWORD_ARCMOVETO = 38;
static const int KEYWORD_ARCTO = 39;
static const int KEYWORD_CLOSE = 40;
// Toolbar Definition
static const int KEYWORD_TOOLBAR = 50;
static const int KEYWORD_PRIORITY = 51;
static const int KEYWORD_TOOL = 52;
static const int KEYWORD_SEPARATOR = 53;
// Operatoren
static const int OPERATOR_SEMICOLON = 1;
static const int OPERATOR_COLON = 2;
static const int OPERATOR_COMMA = 3;
static const int OPERATOR_PERIOD = 4;
static const int OPERATOR_MINUS = 5;
template <typename T, typename U>
QHash<T, U> operator<<(QHash<T, U> hash, QPair<T, U> pair) {
hash.insert(pair.first, pair.second);
return hash;
}
StereotypeDefinitionParserError::StereotypeDefinitionParserError(const QString &error_msg, const SourcePos &source_pos)
: Exception(error_msg),
_source_pos(source_pos)
{
}
StereotypeDefinitionParserError::~StereotypeDefinitionParserError()
{
}
struct StereotypeDefinitionParser::StereotypeDefinitionParserPrivate
{
StereotypeDefinitionParserPrivate()
: _scanner(0)
{
}
TextScanner *_scanner;
};
struct StereotypeDefinitionParser::IconCommandParameter
{
IconCommandParameter(ShapeValueF::Unit unit, ShapeValueF::Origin origin = ShapeValueF::ORIGIN_SMART)
: _unit(unit),
_origin(origin)
{
}
ShapeValueF::Unit _unit;
ShapeValueF::Origin _origin;
};
StereotypeDefinitionParser::StereotypeDefinitionParser(QObject *parent) :
QObject(parent),
d(new StereotypeDefinitionParserPrivate)
{
}
StereotypeDefinitionParser::~StereotypeDefinitionParser()
{
delete d;
}
void StereotypeDefinitionParser::parse(ITextSource *source)
{
TextScanner text_scanner;
text_scanner.setKeywords(
QList<QPair<QString, int> >()
<< qMakePair(QString(QStringLiteral("icon")), KEYWORD_ICON)
<< qMakePair(QString(QStringLiteral("title")), KEYWORD_TITLE)
<< qMakePair(QString(QStringLiteral("elements")), KEYWORD_ELEMENTS)
<< qMakePair(QString(QStringLiteral("stereotype")), KEYWORD_STEREOTYPE)
<< qMakePair(QString(QStringLiteral("width")), KEYWORD_WIDTH)
<< qMakePair(QString(QStringLiteral("height")), KEYWORD_HEIGHT)
<< qMakePair(QString(QStringLiteral("minwidth")), KEYWORD_MINWIDTH)
<< qMakePair(QString(QStringLiteral("minheight")), KEYWORD_MINHEIGHT)
<< qMakePair(QString(QStringLiteral("locksize")), KEYWORD_LOCK_SIZE)
<< qMakePair(QString(QStringLiteral("display")), KEYWORD_DISPLAY)
<< qMakePair(QString(QStringLiteral("textalignment")), KEYWORD_TEXTALIGN)
<< qMakePair(QString(QStringLiteral("basecolor")), KEYWORD_BASECOLOR)
<< qMakePair(QString(QStringLiteral("begin")), KEYWORD_BEGIN)
<< qMakePair(QString(QStringLiteral("end")), KEYWORD_END)
<< qMakePair(QString(QStringLiteral("circle")), KEYWORD_CIRCLE)
<< qMakePair(QString(QStringLiteral("ellipse")), KEYWORD_ELLIPSE)
<< qMakePair(QString(QStringLiteral("line")), KEYWORD_LINE)
<< qMakePair(QString(QStringLiteral("rect")), KEYWORD_RECT)
<< qMakePair(QString(QStringLiteral("roundedrect")), KEYWORD_ROUNDEDRECT)
<< qMakePair(QString(QStringLiteral("arc")), KEYWORD_ARC)
<< qMakePair(QString(QStringLiteral("moveto")), KEYWORD_MOVETO)
<< qMakePair(QString(QStringLiteral("lineto")), KEYWORD_LINETO)
<< qMakePair(QString(QStringLiteral("arcmoveto")), KEYWORD_ARCMOVETO)
<< qMakePair(QString(QStringLiteral("arcto")), KEYWORD_ARCTO)
<< qMakePair(QString(QStringLiteral("close")), KEYWORD_CLOSE)
<< qMakePair(QString(QStringLiteral("toolbar")), KEYWORD_TOOLBAR)
<< qMakePair(QString(QStringLiteral("priority")), KEYWORD_PRIORITY)
<< qMakePair(QString(QStringLiteral("tool")), KEYWORD_TOOL)
<< qMakePair(QString(QStringLiteral("separator")), KEYWORD_SEPARATOR)
);
text_scanner.setOperators(
QList<QPair<QString, int> >()
<< qMakePair(QString(QStringLiteral(";")), OPERATOR_SEMICOLON)
<< qMakePair(QString(QStringLiteral(":")), OPERATOR_COLON)
<< qMakePair(QString(QStringLiteral(",")), OPERATOR_COMMA)
<< qMakePair(QString(QStringLiteral(".")), OPERATOR_PERIOD)
<< qMakePair(QString(QStringLiteral("-")), OPERATOR_MINUS)
);
text_scanner.setSource(source);
d->_scanner = &text_scanner;
try {
parseFile();
} catch (...) {
d->_scanner = 0;
throw;
}
d->_scanner = 0;
}
void StereotypeDefinitionParser::parseFile()
{
for (;;) {
Token token = readNextToken();
if (token.getType() == Token::TOKEN_ENDOFINPUT) {
break;
} else if (token.getType() != Token::TOKEN_KEYWORD || token.getSubtype() == KEYWORD_ICON) {
parseIcon();
} else if (token.getType() != Token::TOKEN_KEYWORD || token.getSubtype() == KEYWORD_TOOLBAR) {
parseToolbar();
} else {
throw StereotypeDefinitionParserError(QStringLiteral("Expected 'icon' or 'toolbar'."), token.getSourcePos());
}
token = d->_scanner->read();
if (token.getType() == Token::TOKEN_OPERATOR && token.getSubtype() == OPERATOR_PERIOD) {
break;
} else if (token.getType() != Token::TOKEN_OPERATOR || token.getSubtype() != OPERATOR_SEMICOLON) {
d->_scanner->unread(token);
}
}
}
void StereotypeDefinitionParser::parseIcon()
{
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_IDENTIFIER && token.getType() != Token::TOKEN_KEYWORD) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected identifier."), token.getSourcePos());
}
QString id = token.getText();
StereotypeIcon stereotype_icon;
stereotype_icon.setId(id);
parseIconProperties(&stereotype_icon);
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD || token.getSubtype() != KEYWORD_BEGIN) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected token 'begin'."), token.getSourcePos());
}
parseIconCommands(&stereotype_icon);
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD || token.getSubtype() != KEYWORD_END) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected token 'end'."), token.getSourcePos());
}
emit iconParsed(stereotype_icon);
}
void StereotypeDefinitionParser::parseIconProperties(StereotypeIcon *stereotype_icon)
{
Token token;
bool loop = true;
QSet<StereotypeIcon::Element> elements;
QSet<QString> stereotypes;
while (loop) {
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD) {
loop = false;
} else {
switch (token.getSubtype()) {
case KEYWORD_TITLE:
stereotype_icon->setTitle(parseStringProperty());
expectSemicolonOrEndOfLine();
break;
case KEYWORD_ELEMENTS:
{
QList<QString> identifiers = parseIdentifierListProperty();
foreach (const QString &identifier, identifiers) {
static QHash<QString, StereotypeIcon::Element> element_names = QHash<QString, StereotypeIcon::Element>()
<< qMakePair(QString(QStringLiteral("package")), StereotypeIcon::ELEMENT_PACKAGE)
<< qMakePair(QString(QStringLiteral("component")), StereotypeIcon::ELEMENT_COMPONENT)
<< qMakePair(QString(QStringLiteral("class")), StereotypeIcon::ELEMENT_CLASS)
<< qMakePair(QString(QStringLiteral("diagram")), StereotypeIcon::ELEMENT_DIAGRAM)
<< qMakePair(QString(QStringLiteral("item")), StereotypeIcon::ELEMENT_ITEM);
QString element_name = identifier.toLower();
if (!element_names.contains(element_name)) {
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(identifier), token.getSourcePos());
}
elements.insert(element_names.value(element_name));
}
expectSemicolonOrEndOfLine();
break;
}
case KEYWORD_STEREOTYPE:
stereotypes.insert(parseStringProperty());
expectSemicolonOrEndOfLine();
break;
case KEYWORD_WIDTH:
stereotype_icon->setWidth(parseFloatProperty());
expectSemicolonOrEndOfLine();
break;
case KEYWORD_HEIGHT:
stereotype_icon->setHeight(parseFloatProperty());
expectSemicolonOrEndOfLine();
break;
case KEYWORD_MINWIDTH:
stereotype_icon->setMinWidth(parseFloatProperty());
expectSemicolonOrEndOfLine();
break;
case KEYWORD_MINHEIGHT:
stereotype_icon->setMinHeight(parseFloatProperty());
expectSemicolonOrEndOfLine();
break;
case KEYWORD_LOCK_SIZE:
{
QString lock_value = parseIdentifierProperty();
QString lock_name = lock_value.toLower();
static QHash<QString, StereotypeIcon::SizeLock> lock_names = QHash<QString, StereotypeIcon::SizeLock>()
<< qMakePair(QString(QStringLiteral("none")), StereotypeIcon::LOCK_NONE)
<< qMakePair(QString(QStringLiteral("width")), StereotypeIcon::LOCK_WIDTH)
<< qMakePair(QString(QStringLiteral("height")), StereotypeIcon::LOCK_HEIGHT)
<< qMakePair(QString(QStringLiteral("size")), StereotypeIcon::LOCK_SIZE)
<< qMakePair(QString(QStringLiteral("ratio")), StereotypeIcon::LOCK_RATIO);
if (lock_names.contains(lock_name)) {
StereotypeIcon::SizeLock size_lock = lock_names.value(lock_name);
stereotype_icon->setSizeLock(size_lock);
} else {
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for size lock.")).arg(lock_value), token.getSourcePos());
}
break;
}
case KEYWORD_DISPLAY:
{
QString display_value = parseIdentifierProperty();
QString display_name = display_value.toLower();
static QHash<QString, StereotypeIcon::Display> display_names = QHash<QString, StereotypeIcon::Display>()
<< qMakePair(QString(QStringLiteral("none")), StereotypeIcon::DISPLAY_NONE)
<< qMakePair(QString(QStringLiteral("label")), StereotypeIcon::DISPLAY_LABEL)
<< qMakePair(QString(QStringLiteral("decoration")), StereotypeIcon::DISPLAY_DECORATION)
<< qMakePair(QString(QStringLiteral("icon")), StereotypeIcon::DISPLAY_ICON)
<< qMakePair(QString(QStringLiteral("smart")), StereotypeIcon::DISPLAY_SMART);
if (display_names.contains(display_name)) {
StereotypeIcon::Display display = display_names.value(display_name);
stereotype_icon->setDisplay(display);
} else {
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for stereotype display.")).arg(display_value), token.getSourcePos());
}
break;
}
case KEYWORD_TEXTALIGN:
{
QString align_value = parseIdentifierProperty();
QString align_name = align_value.toLower();
static QHash<QString, StereotypeIcon::TextAlignment> align_names = QHash<QString, StereotypeIcon::TextAlignment>()
<< qMakePair(QString(QStringLiteral("below")), StereotypeIcon::TEXTALIGN_BELOW)
<< qMakePair(QString(QStringLiteral("center")), StereotypeIcon::TEXTALIGN_CENTER)
<< qMakePair(QString(QStringLiteral("none")), StereotypeIcon::TEXTALIGN_NONE);
if (align_names.contains(align_name)) {
StereotypeIcon::TextAlignment text_alignment = align_names.value(align_name);
stereotype_icon->setTextAlignment(text_alignment);
} else {
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for text alignment.")).arg(align_value), token.getSourcePos());
}
break;
}
case KEYWORD_BASECOLOR:
stereotype_icon->setBaseColor(parseColorProperty());
expectSemicolonOrEndOfLine();
break;
default:
loop = false;
break;
}
}
}
stereotype_icon->setElements(elements);
stereotype_icon->setStereotypes(stereotypes);
d->_scanner->unread(token);
}
void StereotypeDefinitionParser::parseToolbar()
{
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_IDENTIFIER && token.getType() != Token::TOKEN_KEYWORD) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected identifier."), token.getSourcePos());
}
QString id = token.getText();
Toolbar toolbar;
toolbar.setId(id);
parseToolbarProperties(&toolbar);
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD || token.getSubtype() != KEYWORD_BEGIN) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected token 'begin'."), token.getSourcePos());
}
parseToolbarCommands(&toolbar);
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD || token.getSubtype() != KEYWORD_END) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected token 'end'."), token.getSourcePos());
}
emit toolbarParsed(toolbar);
}
void StereotypeDefinitionParser::parseToolbarProperties(Toolbar *toolbar)
{
Token token;
bool loop = true;
while (loop) {
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD) {
loop = false;
} else {
switch (token.getSubtype()) {
case KEYWORD_PRIORITY:
toolbar->setPriority(parseIntProperty());
break;
default:
loop = false;
break;
}
}
}
d->_scanner->unread(token);
}
QString StereotypeDefinitionParser::parseStringProperty()
{
expectColon();
return parseStringExpression();
}
int StereotypeDefinitionParser::parseIntProperty()
{
expectColon();
return parseIntExpression();
}
qreal StereotypeDefinitionParser::parseFloatProperty()
{
expectColon();
return parseFloatExpression();
}
QString StereotypeDefinitionParser::parseIdentifierProperty()
{
expectColon();
return parseIdentifierExpression();
}
QList<QString> StereotypeDefinitionParser::parseIdentifierListProperty()
{
QList<QString> identifiers;
expectColon();
for (;;) {
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_IDENTIFIER && token.getType() != Token::TOKEN_KEYWORD) {
qDebug() << "token" << token.getType() << token.getSubtype() << token.getText();
throw StereotypeDefinitionParserError(QStringLiteral("Expected identifier."), token.getSourcePos());
}
identifiers.append(token.getText());
token = d->_scanner->read();
if (token.getType() != Token::TOKEN_OPERATOR || token.getSubtype() != OPERATOR_COMMA) {
d->_scanner->unread(token);
break;
}
}
return identifiers;
}
bool StereotypeDefinitionParser::parseBoolProperty()
{
expectColon();
return parseBoolExpression();
}
QColor StereotypeDefinitionParser::parseColorProperty()
{
expectColon();
return parseColorExpression();
}
void StereotypeDefinitionParser::parseIconCommands(StereotypeIcon *stereotype_icon)
{
Token token;
bool loop = true;
IconShape icon_shape;
QList<ShapeValueF> parameters;
typedef QList<IconCommandParameter> Parameters;
static const IconCommandParameter SCALED(ShapeValueF::UNIT_SCALED);
static const IconCommandParameter FIX(ShapeValueF::UNIT_RELATIVE);
static const IconCommandParameter ABSOLUTE(ShapeValueF::UNIT_ABSOLUTE);
while (loop) {
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD) {
loop = false;
} else {
switch (token.getSubtype()) {
case KEYWORD_CIRCLE:
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED);
icon_shape.addCircle(ShapePointF(parameters.at(0), parameters.at(1)), parameters.at(2));
expectSemicolonOrEndOfLine();
break;
case KEYWORD_ELLIPSE:
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED << SCALED);
icon_shape.addEllipse(ShapePointF(parameters.at(0), parameters.at(1)), ShapeSizeF(parameters.at(2), parameters.at(3)));
expectSemicolonOrEndOfLine();
break;
case KEYWORD_LINE:
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED << SCALED);
icon_shape.addLine(ShapePointF(parameters.at(0), parameters.at(1)), ShapePointF(parameters.at(2), parameters.at(3)));
expectSemicolonOrEndOfLine();
break;
case KEYWORD_RECT:
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED << SCALED);
icon_shape.addRect(ShapePointF(parameters.at(0), parameters.at(1)), ShapeSizeF(parameters.at(2), parameters.at(3)));
expectSemicolonOrEndOfLine();
break;
case KEYWORD_ROUNDEDRECT:
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED << SCALED << FIX);
icon_shape.addRoundedRect(ShapePointF(parameters.at(0), parameters.at(1)), ShapeSizeF(parameters.at(2), parameters.at(3)), parameters.at(4));
expectSemicolonOrEndOfLine();
break;
case KEYWORD_ARC:
{
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED << SCALED << ABSOLUTE << ABSOLUTE);
qreal start_angle = expectAbsoluteValue(parameters.at(4), d->_scanner->getSourcePos());
qreal span_angle = expectAbsoluteValue(parameters.at(5), d->_scanner->getSourcePos());
icon_shape.addArc(ShapePointF(parameters.at(0), parameters.at(1)), ShapeSizeF(parameters.at(2), parameters.at(3)), start_angle, span_angle);
expectSemicolonOrEndOfLine();
break;
}
case KEYWORD_MOVETO:
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED);
icon_shape.moveTo(ShapePointF(parameters.at(0), parameters.at(1)));
expectSemicolonOrEndOfLine();
break;
case KEYWORD_LINETO:
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED);
icon_shape.lineTo(ShapePointF(parameters.at(0), parameters.at(1)));
expectSemicolonOrEndOfLine();
break;
case KEYWORD_ARCMOVETO:
{
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED << SCALED << ABSOLUTE);
qreal angle = expectAbsoluteValue(parameters.at(4), d->_scanner->getSourcePos());
icon_shape.arcMoveTo(ShapePointF(parameters.at(0), parameters.at(1)), ShapeSizeF(parameters.at(2), parameters.at(3)), angle);
expectSemicolonOrEndOfLine();
break;
}
case KEYWORD_ARCTO:
{
parameters = parseIconCommandParameters(Parameters() << SCALED << SCALED << SCALED << SCALED << ABSOLUTE << ABSOLUTE);
qreal start_angle = expectAbsoluteValue(parameters.at(4), d->_scanner->getSourcePos());
qreal sweep_length = expectAbsoluteValue(parameters.at(5), d->_scanner->getSourcePos());
icon_shape.arcTo(ShapePointF(parameters.at(0), parameters.at(1)), ShapeSizeF(parameters.at(2), parameters.at(3)), start_angle, sweep_length);
expectSemicolonOrEndOfLine();
break;
}
case KEYWORD_CLOSE:
icon_shape.closePath();
expectSemicolonOrEndOfLine();
break;
default:
loop = false;
break;
}
}
}
stereotype_icon->setIconShape(icon_shape);
d->_scanner->unread(token);
}
QList<ShapeValueF> StereotypeDefinitionParser::parseIconCommandParameters(const QList<IconCommandParameter> &parameters)
{
QList<ShapeValueF> values;
Token token;
for (;;) {
if (values.count() <= parameters.count()) {
values << ShapeValueF(parseFloatExpression(), parameters.at(values.count())._unit, parameters.at(values.count())._origin);
} else {
values << ShapeValueF(parseFloatExpression());
}
token = d->_scanner->read();
if (token.getType() != Token::TOKEN_OPERATOR || token.getSubtype() != OPERATOR_COMMA) {
d->_scanner->unread(token);
break;
}
}
if (values.count() < parameters.count()) {
throw StereotypeDefinitionParserError(QStringLiteral("More parameters expected."), token.getSourcePos());
} else if (values.count() > parameters.count()) {
throw StereotypeDefinitionParserError(QStringLiteral("Too many parameters given."), token.getSourcePos());
}
return values;
}
void StereotypeDefinitionParser::parseToolbarCommands(Toolbar *toolbar)
{
Token token;
QList<Toolbar::Tool> tools;
bool loop = true;
while (loop) {
token = readNextToken();
if (token.getType() != Token::TOKEN_KEYWORD) {
loop = false;
} else {
switch (token.getSubtype()) {
case KEYWORD_TOOL:
{
QString tool_name = parseStringExpression();
expectComma();
QString element = parseIdentifierExpression();
static QSet<QString> element_names = QSet<QString>()
<< QStringLiteral("package")
<< QStringLiteral("component")
<< QStringLiteral("class")
<< QStringLiteral("item")
<< QStringLiteral("annotation")
<< QStringLiteral("boundary");
QString element_name = element.toLower();
if (!element_names.contains(element_name)) {
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(element), token.getSourcePos());
}
QString stereotype;
if (nextIsComma()) {
stereotype = parseStringExpression();
}
tools.append(Toolbar::Tool(tool_name, element, stereotype));
expectSemicolonOrEndOfLine();
break;
}
case KEYWORD_SEPARATOR:
tools.append(Toolbar::Tool());
expectSemicolonOrEndOfLine();
break;
default:
loop = false;
break;
}
}
}
toolbar->setTools(tools);
d->_scanner->unread(token);
}
QString StereotypeDefinitionParser::parseStringExpression()
{
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_STRING) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected string constant."), token.getSourcePos());
}
return token.getText();
}
qreal StereotypeDefinitionParser::parseFloatExpression()
{
Token token;
token = d->_scanner->read();
if (token.getType() == Token::TOKEN_OPERATOR && token.getSubtype() == OPERATOR_MINUS) {
return -parseFloatExpression();
} else {
bool ok = false;
if (token.getType() == Token::TOKEN_INTEGER) {
int value = token.getText().toInt(&ok);
QMT_CHECK(ok);
return value;
} else if (token.getType() == Token::TOKEN_FLOAT) {
qreal value = token.getText().toDouble(&ok);
QMT_CHECK(ok);
return value;
} else {
throw StereotypeDefinitionParserError(QStringLiteral("Expected number constant."), token.getSourcePos());
}
}
}
int StereotypeDefinitionParser::parseIntExpression()
{
Token token;
token = d->_scanner->read();
if (token.getType() == Token::TOKEN_OPERATOR && token.getSubtype() == OPERATOR_MINUS) {
return -parseIntExpression();
} else {
bool ok = false;
if (token.getType() == Token::TOKEN_INTEGER) {
int value = token.getText().toInt(&ok);
QMT_CHECK(ok);
return value;
} else {
throw StereotypeDefinitionParserError(QStringLiteral("Expected integer constant."), token.getSourcePos());
}
}
}
QString StereotypeDefinitionParser::parseIdentifierExpression()
{
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_IDENTIFIER && token.getType() != Token::TOKEN_KEYWORD) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected identifier."), token.getSourcePos());
}
return token.getText();
}
bool StereotypeDefinitionParser::parseBoolExpression()
{
Token token = d->_scanner->read();
if (token.getType() == Token::TOKEN_IDENTIFIER) {
QString value = token.getText().toLower();
if (value == QStringLiteral("yes") || value == QStringLiteral("true")) {
return true;
} else if (value == QStringLiteral("no") || value == QStringLiteral("false")) {
return false;
}
}
throw StereotypeDefinitionParserError(QStringLiteral("Expected 'yes', 'no', 'true' or 'false'."), token.getSourcePos());
}
QColor StereotypeDefinitionParser::parseColorExpression()
{
Token token = d->_scanner->read();
if (token.getType() == Token::TOKEN_IDENTIFIER || token.getType() == Token::TOKEN_COLOR) {
QString value = token.getText().toLower();
QColor color;
if (QColor::isValidColor(value)) {
color.setNamedColor(value);
return color;
}
}
throw StereotypeDefinitionParserError(QStringLiteral("Expected color name."), token.getSourcePos());
}
Token StereotypeDefinitionParser::readNextToken()
{
Token token;
for (;;) {
token = d->_scanner->read();
if (token.getType() != Token::TOKEN_ENDOFLINE) {
return token;
}
}
}
qreal StereotypeDefinitionParser::expectAbsoluteValue(const ShapeValueF &value, const SourcePos &source_pos)
{
if (value.getUnit() != ShapeValueF::UNIT_ABSOLUTE || value.getOrigin() != ShapeValueF::ORIGIN_SMART) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected absolute value"), source_pos);
}
return value.getValue();
}
void StereotypeDefinitionParser::expectSemicolonOrEndOfLine()
{
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_ENDOFLINE && (token.getType() != Token::TOKEN_OPERATOR || token.getSubtype() != OPERATOR_SEMICOLON)) {
throw StereotypeDefinitionParserError(QStringLiteral("Expected ';' or end-of-line."), token.getSourcePos());
}
}
bool StereotypeDefinitionParser::nextIsComma()
{
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_OPERATOR || token.getSubtype() != OPERATOR_COMMA) {
d->_scanner->unread(token);
return false;
}
return true;
}
void StereotypeDefinitionParser::expectOperator(int op, const QString &op_name)
{
Token token = d->_scanner->read();
if (token.getType() != Token::TOKEN_OPERATOR || token.getSubtype() != op) {
throw StereotypeDefinitionParserError(QString(QStringLiteral("Expected '%1'.")).arg(op_name), token.getSourcePos());
}
}
void StereotypeDefinitionParser::expectComma()
{
expectOperator(OPERATOR_COMMA, QStringLiteral(","));
}
void StereotypeDefinitionParser::expectColon()
{
expectOperator(OPERATOR_COLON, QStringLiteral(":"));
}
}

View File

@@ -0,0 +1,155 @@
/***************************************************************************
**
** 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 QMT_STEREOTYPEDEFINITIONPARSER_H
#define QMT_STEREOTYPEDEFINITIONPARSER_H
#include <QObject>
#include "qmt/infrastructure/exceptions.h"
#include "sourcepos.h"
namespace qmt {
class ITextSource;
class Token;
class StereotypeIcon;
class Toolbar;
class ShapeValueF;
class QMT_EXPORT StereotypeDefinitionParserError :
public Exception
{
public:
StereotypeDefinitionParserError(const QString &error_msg, const SourcePos &source_pos);
~StereotypeDefinitionParserError();
public:
SourcePos getSourcePos() const { return _source_pos; }
private:
SourcePos _source_pos;
};
class QMT_EXPORT StereotypeDefinitionParser : public QObject
{
Q_OBJECT
struct StereotypeDefinitionParserPrivate;
struct IconCommandParameter;
public:
explicit StereotypeDefinitionParser(QObject *parent = 0);
~StereotypeDefinitionParser();
signals:
void iconParsed(const StereotypeIcon &stereotype_icon);
void toolbarParsed(const Toolbar &toolbar);
public:
void parse(ITextSource *source);
private:
void parseFile();
void parseIcon();
void parseIconProperties(StereotypeIcon *stereotype_icon);
void parseToolbar();
void parseToolbarProperties(Toolbar *toolbar);
QString parseStringProperty();
int parseIntProperty();
qreal parseFloatProperty();
QString parseIdentifierProperty();
QList<QString> parseIdentifierListProperty();
bool parseBoolProperty();
QColor parseColorProperty();
void parseIconCommands(StereotypeIcon *stereotype_icon);
QList<ShapeValueF> parseIconCommandParameters(const QList<IconCommandParameter> &parameters);
void parseToolbarCommands(Toolbar *toolbar);
QString parseStringExpression();
qreal parseFloatExpression();
int parseIntExpression();
QString parseIdentifierExpression();
bool parseBoolExpression();
QColor parseColorExpression();
Token readNextToken();
qreal expectAbsoluteValue(const ShapeValueF &value, const SourcePos &source_pos);
void expectSemicolonOrEndOfLine();
bool nextIsComma();
void expectOperator(int op, const QString &op_name);
void expectComma();
void expectColon();
private:
StereotypeDefinitionParserPrivate *d;
};
}
#endif // QMT_STEREOTYPEDEFINITIONPARSER_H

View File

@@ -0,0 +1,86 @@
/***************************************************************************
**
** 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 "stringtextsource.h"
#include "sourcepos.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
StringTextSource::StringTextSource()
: _source_id(-1),
_index(-1),
_line_number(-1),
_column_number(-1)
{
}
StringTextSource::~StringTextSource()
{
}
void StringTextSource::setText(const QString &text)
{
_text = text;
_index = 0;
_line_number = 1;
_column_number = 1;
}
void StringTextSource::setSourceId(int source_id)
{
_source_id = source_id;
}
SourceChar StringTextSource::readNextChar()
{
QMT_CHECK(_source_id >= 0);
QMT_CHECK(_index >= 0);
QMT_CHECK(_line_number >= 0);
QMT_CHECK(_column_number >= 0);
if (_index >= _text.length()) {
return SourceChar(QChar(), SourcePos(_source_id, _line_number, _column_number));
}
SourcePos pos(_source_id, _line_number, _column_number);
QChar ch(_text.at(_index));
++_index;
if (ch == QChar::LineFeed) {
++_line_number;
_column_number = 1;
} else {
++_column_number;
}
return SourceChar(ch, pos);
}
} // namespace qmt

View File

@@ -0,0 +1,76 @@
/***************************************************************************
**
** 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 QMT_STRINGTEXTSOURCE_H
#define QMT_STRINGTEXTSOURCE_H
#include "textsource.h"
#include <QString>
namespace qmt {
class QMT_EXPORT StringTextSource :
public ITextSource
{
public:
StringTextSource();
~StringTextSource();
public:
void setText(const QString &text);
int getSourceId() const { return _source_id; }
void setSourceId(int source_id);
// ITextSource interface
public:
SourceChar readNextChar();
private:
QString _text;
int _source_id;
int _index;
int _line_number;
int _column_number;
};
} // namespace qmt
#endif // QMT_STRINGTEXTSOURCE_H

View File

@@ -0,0 +1,321 @@
/***************************************************************************
**
** 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 "textscanner.h"
#include "textsource.h"
#include "token.h"
#include "qmt/infrastructure/qmtassert.h"
#include <QHash>
#include <QSet>
#include <QStack>
#include <QPair>
typedef QPair<QString, int> DefTuple;
namespace qmt {
TextScannerError::TextScannerError(const QString &error_msg, const SourcePos &source_pos)
: Exception(error_msg),
_source_pos(source_pos)
{
}
TextScannerError::~TextScannerError()
{
}
struct TextScanner::TextScannerPrivate {
TextScannerPrivate()
: _max_operator_length(0),
_source(0)
{
}
QHash<QString, int> _keyword_to_subtype_map;
QHash<QString, int> _operator_to_subtype_map;
int _max_operator_length;
QSet<QChar> _operator_first_chars_set;
QSet<QChar> _operator_chars_set;
ITextSource *_source;
QStack<SourceChar> _unread_source_chars;
SourcePos _last_source_pos;
QStack<Token> _unread_tokens;
};
TextScanner::TextScanner(QObject *parent) :
QObject(parent),
d(new TextScannerPrivate)
{
}
TextScanner::~TextScanner()
{
delete d;
}
void TextScanner::setKeywords(const QList<QPair<QString, int> > &keywords)
{
d->_keyword_to_subtype_map.clear();
foreach (const DefTuple &tuple, keywords) {
d->_keyword_to_subtype_map.insert(tuple.first.toLower(), tuple.second);
}
}
void TextScanner::setOperators(const QList<QPair<QString, int> > &operators)
{
d->_operator_to_subtype_map.clear();
d->_max_operator_length = 0;
d->_operator_first_chars_set.clear();
d->_operator_chars_set.clear();
foreach (const DefTuple &tuple, operators) {
QString op = tuple.first;
d->_operator_to_subtype_map.insert(op, tuple.second);
if (op.length() > d->_max_operator_length) {
d->_max_operator_length = op.length();
}
d->_operator_first_chars_set.insert(op.at(0));
foreach (const QChar ch, op) {
d->_operator_chars_set.insert(ch);
}
}
}
void TextScanner::setSource(ITextSource *text_source)
{
d->_source = text_source;
}
SourcePos TextScanner::getSourcePos() const
{
return d->_last_source_pos;
}
Token TextScanner::read()
{
if (!d->_unread_tokens.isEmpty()) {
return d->_unread_tokens.pop();
}
skipWhitespaces();
SourceChar source_char = readChar();
if (source_char.ch == QLatin1Char('\'') || source_char.ch == QLatin1Char('\"')) {
return scanString(source_char);
} else if (source_char.ch.isDigit()) {
return scanNumber(source_char);
} else if (source_char.ch.isLetter() || source_char.ch == QLatin1Char('_')) {
return scanIdentifier(source_char);
} else if (source_char.ch == QLatin1Char('#')) {
return scanColorIdentifier(source_char);
} else if (source_char.ch == QChar::LineFeed || source_char.ch == QChar::CarriageReturn) {
return Token(Token::TOKEN_ENDOFLINE, QString(), source_char.pos);
} else if (source_char.ch.isNull()) {
return Token(Token::TOKEN_ENDOFINPUT, QString(), source_char.pos);
} else if (d->_operator_first_chars_set.contains(source_char.ch)) {
return scanOperator(source_char);
} else {
throw TextScannerError(QStringLiteral("Unexpected character."), source_char.pos);
}
}
void TextScanner::unread(const Token &token)
{
d->_unread_tokens.push(token);
}
SourceChar TextScanner::readChar()
{
SourceChar ch;
if (!d->_unread_source_chars.isEmpty()) {
ch = d->_unread_source_chars.pop();
} else {
ch = d->_source->readNextChar();
}
d->_last_source_pos = ch.pos;
return ch;
}
void TextScanner::unreadChar(const SourceChar &source_char)
{
d->_unread_source_chars.push(source_char);
}
void TextScanner::skipWhitespaces()
{
for (;;) {
SourceChar source_char = readChar();
if (source_char.ch == QLatin1Char('/')) {
SourceChar second_source_char = readChar();
if (second_source_char.ch == QLatin1Char('/')) {
for (;;) {
SourceChar comment_char = readChar();
if (comment_char.ch.isNull() || comment_char.ch == QChar::LineFeed || comment_char.ch == QChar::CarriageReturn) {
break;
}
}
} else {
unreadChar(second_source_char);
unreadChar(source_char);
}
} else if (source_char.ch == QChar::LineFeed || source_char.ch == QChar::CarriageReturn || !source_char.ch.isSpace()) {
unreadChar(source_char);
return;
}
}
}
Token TextScanner::scanString(const SourceChar &delimiter_char)
{
QString text;
for (;;) {
SourceChar source_char = readChar();
if (source_char.ch == delimiter_char.ch) {
return Token(Token::TOKEN_STRING, text, delimiter_char.pos);
} else if (source_char.ch == QLatin1Char('\\')) {
source_char = readChar();
if (source_char.ch == QLatin1Char('n')) {
text += QLatin1Char('\n');
} else if (source_char.ch == QLatin1Char('\\')) {
text += QLatin1Char('\\');
} else if (source_char.ch == QLatin1Char('t')) {
text += QLatin1Char('\t');
} else if (source_char.ch == QLatin1Char('\"')) {
text += QLatin1Char('\"');
} else if (source_char.ch == QLatin1Char('\'')) {
text += QLatin1Char('\'');
} else {
throw TextScannerError(QStringLiteral("Unexpected character after '\\' in string constant."), source_char.pos);
}
} else if (source_char.ch == QChar::LineFeed || source_char.ch == QChar::CarriageReturn) {
throw TextScannerError(QStringLiteral("Unexpected end of line in string constant."), source_char.pos);
} else {
text += source_char.ch;
}
}
}
Token TextScanner::scanNumber(const SourceChar &first_digit)
{
QString text = first_digit.ch;
SourceChar source_char;
for (;;) {
source_char = readChar();
if (!source_char.ch.isDigit()) {
break;
}
text += source_char.ch;
}
if (source_char.ch == QLatin1Char('.')) {
text += source_char.ch;
for (;;) {
source_char = readChar();
if (!source_char.ch.isDigit()) {
break;
}
text += source_char.ch;
}
unreadChar(source_char);
return Token(Token::TOKEN_FLOAT, text, first_digit.pos);
} else {
unreadChar(source_char);
return Token(Token::TOKEN_INTEGER, text, first_digit.pos);
}
}
Token TextScanner::scanIdentifier(const SourceChar &first_char)
{
QString text = first_char.ch;
SourceChar source_char;
for (;;) {
source_char = readChar();
if (!source_char.ch.isLetterOrNumber() && source_char.ch != QLatin1Char('_')) {
unreadChar(source_char);
QString keyword = text.toLower();
if (d->_keyword_to_subtype_map.contains(keyword)) {
return Token(Token::TOKEN_KEYWORD, d->_keyword_to_subtype_map.value(keyword), text, first_char.pos);
}
return Token(Token::TOKEN_IDENTIFIER, text, first_char.pos);
}
text += source_char.ch;
}
}
Token TextScanner::scanColorIdentifier(const SourceChar &first_char)
{
QString text = first_char.ch;
SourceChar source_char;
for (;;) {
source_char = readChar();
QChar ch = source_char.ch.toLower();
if (!(ch.isDigit() || (ch >= QLatin1Char('a') && ch <= QLatin1Char('f')))) {
unreadChar(source_char);
return Token(Token::TOKEN_COLOR, text, first_char.pos);
}
text += source_char.ch;
}
}
Token TextScanner::scanOperator(const SourceChar &first_char)
{
QString text = first_char.ch;
SourceChar source_char;
QStack<SourceChar> extra_chars;
bool have_operator = false;
int operator_length = 0;
int subtype = 0;
QString op;
extra_chars.push(first_char);
for (;;) {
if (d->_operator_to_subtype_map.contains(text)) {
have_operator = true;
operator_length = text.length();
subtype = d->_operator_to_subtype_map.value(text);
op = text;
}
source_char = readChar();
if (text.length() >= d->_max_operator_length || !d->_operator_chars_set.contains(source_char.ch)) {
unreadChar(source_char);
int i = text.length();
while (i > operator_length) {
--i;
unreadChar(extra_chars.pop());
}
QMT_CHECK(have_operator);
Q_UNUSED(have_operator); // avoid warning in release mode
return Token(Token::TOKEN_OPERATOR, subtype, op, first_char.pos);
}
text += source_char.ch;
extra_chars.push(source_char);
}
}
} // namespace qmt

View File

@@ -0,0 +1,119 @@
/***************************************************************************
**
** 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 QMT_TEXTSCANNER_H
#define QMT_TEXTSCANNER_H
#include <QObject>
#include "sourcepos.h"
#include "qmt/infrastructure/exceptions.h"
namespace qmt {
class ITextSource;
struct SourceChar;
class Token;
class QMT_EXPORT TextScannerError :
public Exception
{
public:
TextScannerError(const QString &error_msg, const SourcePos &source_pos);
~TextScannerError();
public:
SourcePos getSourcePos() const { return _source_pos; }
private:
SourcePos _source_pos;
};
class QMT_EXPORT TextScanner : public QObject
{
Q_OBJECT
struct TextScannerPrivate;
public:
explicit TextScanner(QObject *parent = 0);
~TextScanner();
signals:
public:
void setKeywords(const QList<QPair<QString, int> > &keywords);
void setOperators(const QList<QPair<QString, int> > &operators);
void setSource(ITextSource *text_source);
SourcePos getSourcePos() const;
public:
Token read();
void unread(const Token &token);
private:
SourceChar readChar();
void unreadChar(const SourceChar &source_char);
void skipWhitespaces();
Token scanString(const SourceChar &delimiter_char);
Token scanNumber(const SourceChar &first_digit);
Token scanIdentifier(const SourceChar &first_char);
Token scanColorIdentifier(const SourceChar &first_char);
Token scanOperator(const SourceChar &first_char);
private:
TextScannerPrivate *d;
};
} // namespace qmt
#endif // QMT_TEXTSCANNER_H

View File

@@ -0,0 +1,65 @@
/***************************************************************************
**
** 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 QMT_TEXTSOURCE_H
#define QMT_TEXTSOURCE_H
#include "sourcepos.h"
#include <QChar>
namespace qmt {
struct SourceChar {
SourceChar() { }
SourceChar(QChar chr, const SourcePos &source_pos)
: ch(chr),
pos(source_pos)
{
}
QChar ch;
SourcePos pos;
};
class ITextSource
{
public:
virtual ~ITextSource() { }
virtual SourceChar readNextChar() = 0;
};
}
#endif // QMT_TEXTSOURCE_H

View File

@@ -0,0 +1,81 @@
/***************************************************************************
**
** 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 "token.h"
namespace qmt {
Token::Token()
: _type(TOKEN_UNDEFINED),
_subtype(0)
{
}
Token::Token(Type type, const QString &text, const SourcePos &source_pos)
: _type(type),
_subtype(0),
_text(text),
_source_pos(source_pos)
{
}
Token::Token(Token::Type type, int subtype, const QString &text, const SourcePos &source_pos)
: _type(type),
_subtype(subtype),
_text(text),
_source_pos(source_pos)
{
}
Token::~Token()
{
}
void Token::setType(Token::Type type)
{
_type = type;
}
void Token::setSubtype(int subtype)
{
_subtype = subtype;
}
void Token::setText(const QString &text)
{
_text = text;
}
void Token::setSourcePos(const SourcePos &source_pos)
{
_source_pos = source_pos;
}
} // namespace qmt

View File

@@ -0,0 +1,90 @@
/***************************************************************************
**
** 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 QMT_TOKEN_H
#define QMT_TOKEN_H
#include "sourcepos.h"
#include <QString>
namespace qmt {
class Token
{
public:
enum Type {
TOKEN_UNDEFINED,
TOKEN_ENDOFINPUT,
TOKEN_ENDOFLINE,
TOKEN_STRING,
TOKEN_INTEGER,
TOKEN_FLOAT,
TOKEN_IDENTIFIER,
TOKEN_KEYWORD,
TOKEN_OPERATOR,
TOKEN_COLOR
};
public:
Token();
Token(Type type, const QString &text, const SourcePos &source_pos);
Token(Type type, int subtype, const QString &text, const SourcePos &source_pos);
~Token();
public:
Type getType() const { return _type; }
void setType(Type type);
int getSubtype() const { return _subtype; }
void setSubtype(int subtype);
QString getText() const { return _text; }
void setText(const QString &text);
SourcePos getSourcePos() const { return _source_pos; }
void setSourcePos(const SourcePos &source_pos);
private:
Type _type;
int _subtype;
QString _text;
SourcePos _source_pos;
};
} // namespace qmt
#endif // QMT_TOKEN_H

View File

@@ -0,0 +1,109 @@
/***************************************************************************
**
** 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 QMT_CONTAINER_H
#define QMT_CONTAINER_H
#include <QList>
namespace qmt {
template<class T>
class Container
{
protected:
Container() { }
Container(const Container<T> &rhs)
: _elements(rhs._elements)
{
rhs._elements.clear();
}
public:
~Container()
{
qDeleteAll(_elements);
}
public:
Container &operator=(const Container<T> &rhs)
{
if (this != &rhs) {
qDeleteAll(_elements);
_elements = rhs._elements;
rhs._elements.clear();
}
return *this;
}
public:
bool isEmpty() const { return _elements.empty(); }
int size() const { return _elements.size(); }
QList<T *> getElements() const { return _elements; }
QList<T *> takeElements() const
{
QList<T *> elements = _elements;
_elements.clear();
return elements;
}
void submitElements(const QList<T *> &elements)
{
qDeleteAll(_elements);
_elements = elements;
}
void reset()
{
qDeleteAll(_elements);
_elements.clear();
}
void submit(T *element)
{
_elements.append(element);
}
private:
mutable QList<T *> _elements;
};
}
#endif // QMT_CONTAINER_H

View File

@@ -0,0 +1,162 @@
/***************************************************************************
**
** 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 "namecontroller.h"
#include <QFileInfo>
#include <QDebug>
namespace qmt {
NameController::NameController(QObject *parent)
: QObject(parent)
{
}
NameController::~NameController()
{
}
QString NameController::convertFileNameToElementName(const QString &file_name)
{
QFileInfo file_info(file_name);
QString base_name = file_info.baseName().trimmed();
QString element_name;
bool make_uppercase = true;
bool insert_space = false;
for (int i = 0; i < base_name.size(); ++i) {
if (base_name.at(i) == QLatin1Char('_')) {
make_uppercase = true;
insert_space = true;
} else if (base_name.at(i) == QLatin1Char(' ') || base_name.at(i) == QLatin1Char('-')) {
make_uppercase = true;
insert_space = false;
element_name += base_name.at(i);
} else if (make_uppercase) {
if (insert_space) {
element_name += QLatin1Char(' ');
insert_space = false;
}
element_name += base_name.at(i).toUpper();
make_uppercase = false;
} else {
if (insert_space) {
element_name += QLatin1Char(' ');
insert_space = false;
}
element_name += base_name.at(i);
}
}
return element_name;
}
QString NameController::convertElementNameToBaseFileName(const QString &element_name)
{
QString base_file_name;
bool insert_underscore = false;
for (int i = 0; i < element_name.size(); ++i) {
if (element_name.at(i) == QLatin1Char(' ')) {
insert_underscore = true;
} else {
if (insert_underscore) {
base_file_name += QLatin1Char('_');
insert_underscore = false;
}
base_file_name += element_name.at(i).toLower();
}
}
return base_file_name;
}
QString NameController::calcRelativePath(const QString &absolute_file_name, const QString &anchor_path)
{
int second_last_slash_index = -1;
int slash_index = -1;
int i = 0;
while (i < absolute_file_name.size() && i < anchor_path.size() && absolute_file_name.at(i) == anchor_path.at(i)) {
if (absolute_file_name.at(i) == QLatin1Char('/')) {
second_last_slash_index = slash_index;
slash_index = i;
}
++i;
}
QString relative_path;
if (slash_index < 0) {
relative_path = absolute_file_name;
} else if (i >= absolute_file_name.size()) {
// absolute_file_name is a substring of anchor path.
if (slash_index == i - 1) {
if (second_last_slash_index < 0) {
relative_path = absolute_file_name;
} else {
relative_path = absolute_file_name.mid(second_last_slash_index + 1);
}
} else {
relative_path = absolute_file_name.mid(slash_index + 1);
}
} else {
relative_path = absolute_file_name.mid(slash_index + 1);
}
return relative_path;
}
QString NameController::calcElementNameSearchId(const QString &element_name)
{
QString search_id;
foreach (const QChar &c, element_name) {
if (c.isLetterOrNumber()) {
search_id += c.toLower();
}
}
return search_id;
}
QList<QString> NameController::buildElementsPath(const QString &file_path, bool ignore_last_file_path_part)
{
QList<QString> relative_elements;
QStringList splitted = file_path.split(QStringLiteral("/"));
QStringList::const_iterator splitted_end = splitted.end();
if (ignore_last_file_path_part || splitted.last().isEmpty()) {
splitted_end = --splitted_end;
}
for (QStringList::const_iterator it = splitted.cbegin(); it != splitted_end; ++it) {
QString package_name = qmt::NameController::convertFileNameToElementName(*it);
relative_elements.append(package_name);
}
return relative_elements;
}
}

View File

@@ -0,0 +1,70 @@
/***************************************************************************
**
** 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 QMT_NAMECONTROLLER_H
#define QMT_NAMECONTROLLER_H
#include <QObject>
#include "qmt/infrastructure/qmt_global.h"
#include <QString>
#include <QList>
namespace qmt {
class QMT_EXPORT NameController :
public QObject
{
Q_OBJECT
private:
NameController(QObject *parent = 0);
~NameController();
public:
static QString convertFileNameToElementName(const QString &file_name);
static QString convertElementNameToBaseFileName(const QString &element_name);
static QString calcRelativePath(const QString &absolute_file_name, const QString &anchor_path);
static QString calcElementNameSearchId(const QString &element_name);
static QList<QString> buildElementsPath(const QString &file_path, bool ignore_last_file_path_part);
private:
};
}
#endif // QMT_NAMECONTROLLER_H

View File

@@ -0,0 +1,69 @@
/***************************************************************************
**
** 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 QMT_REFERENCES_H
#define QMT_REFERENCES_H
#include <QList>
namespace qmt {
template<class T>
class References
{
protected:
References() { }
public:
~References() { }
public:
bool isEmpty() const { return _elements.empty(); }
int size() const { return _elements.size(); }
QList<T *> getElements() const { return _elements; }
void setElements(const QList<T *> &elements) { _elements = elements; }
void clear() { _elements.clear(); }
void append(T *element) { _elements.append(element); }
private:
QList<T *> _elements;
};
}
#endif // QMT_REFERENCES_H

View File

@@ -0,0 +1,63 @@
/***************************************************************************
**
** 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 "selection.h"
namespace qmt {
Selection::Selection()
{
}
Selection::~Selection()
{
}
void Selection::setIndices(const QList<qmt::Selection::Index> &indices)
{
_indices = indices;
}
void Selection::clear()
{
_indices.clear();
}
void Selection::append(const Index &index)
{
_indices.append(index);
}
void Selection::append(const Uid &element_key, const Uid &owner_key)
{
append(Index(element_key, owner_key));
}
}

View File

@@ -0,0 +1,96 @@
/***************************************************************************
**
** 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 QMT_SELECTION_H
#define QMT_SELECTION_H
#include "qmt/infrastructure/uid.h"
#include <QList>
namespace qmt {
class QMT_EXPORT Selection
{
public:
class Index {
public:
Index(const Uid &element_key, const Uid &owner_key)
: _element_key(element_key),
_owner_key(owner_key)
{
}
Uid getElementKey() const { return _element_key; }
Uid getOwnerKey() const { return _owner_key; }
private:
Uid _element_key;
Uid _owner_key;
};
protected:
Selection();
public:
~Selection();
public:
bool isEmpty() const { return _indices.isEmpty(); }
QList<Index> getIndices() const { return _indices; }
void setIndices(const QList<Index> &indices);
public:
void clear();
void append(const Index &index);
void append(const Uid &element_key, const Uid &owner_key);
private:
QList<Index> _indices;
};
}
#endif // QMT_SELECTION_H

View File

@@ -0,0 +1,89 @@
/***************************************************************************
**
** 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 "undocommand.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
UndoCommand::UndoCommand(const QString &text)
: QUndoCommand(text),
_can_redo(false),
_do_not_merge(false)
{
}
UndoCommand::~UndoCommand()
{
}
int UndoCommand::id() const
{
return 1;
}
void UndoCommand::setDoNotMerge(bool do_not_merge)
{
_do_not_merge = do_not_merge;
}
bool UndoCommand::mergeWith(const QUndoCommand *other)
{
const UndoCommand *other_command = dynamic_cast<const UndoCommand *>(other);
if (!other_command) {
return false;
}
if (other_command->_do_not_merge) {
return false;
}
return mergeWith(other_command);
}
bool UndoCommand::mergeWith(const UndoCommand *other)
{
Q_UNUSED(other);
return false;
}
void UndoCommand::undo()
{
QMT_CHECK(!_can_redo);
_can_redo = true;
}
void UndoCommand::redo()
{
QMT_CHECK(_can_redo);
_can_redo = false;
}
}

View File

@@ -0,0 +1,75 @@
/***************************************************************************
**
** 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 QMT_UNDOCOMMAND_H
#define QMT_UNDOCOMMAND_H
#include <QUndoCommand>
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class QMT_EXPORT UndoCommand :
public QUndoCommand
{
public:
explicit UndoCommand(const QString &text);
~UndoCommand();
public:
bool canRedo() const { return _can_redo; }
int id() const;
void setDoNotMerge(bool do_not_merge);
public:
bool mergeWith(const QUndoCommand *other);
virtual bool mergeWith(const UndoCommand *other);
void undo();
void redo();
private:
bool _can_redo;
bool _do_not_merge;
};
}
#endif // QMT_UNDOCOMMAND_H

View File

@@ -0,0 +1,77 @@
/***************************************************************************
**
** 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 "undocontroller.h"
#include "undocommand.h"
#include <QUndoStack>
namespace qmt {
UndoController::UndoController(QObject *parent) :
QObject(parent),
_undo_stack(new QUndoStack(this)),
_do_not_merge(false)
{
}
UndoController::~UndoController()
{
}
void UndoController::push(UndoCommand *cmd)
{
cmd->setDoNotMerge(_do_not_merge);
_do_not_merge = false;
_undo_stack->push(cmd);
}
void UndoController::beginMergeSequence(const QString &text)
{
_undo_stack->beginMacro(text);
}
void UndoController::endMergeSequence()
{
_undo_stack->endMacro();
}
void UndoController::reset()
{
_undo_stack->clear();
}
void UndoController::doNotMerge()
{
_do_not_merge = true;
}
}

View File

@@ -0,0 +1,88 @@
/***************************************************************************
**
** 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 QMT_UNDOCONTROLLER_H
#define QMT_UNDOCONTROLLER_H
#include <QObject>
#include "qmt/infrastructure/qmt_global.h"
QT_BEGIN_NAMESPACE
class QUndoStack;
QT_END_NAMESPACE
namespace qmt {
class UndoCommand;
class QMT_EXPORT UndoController :
public QObject
{
Q_OBJECT
public:
explicit UndoController(QObject *parent = 0);
~UndoController();
signals:
public:
QUndoStack *getUndoStack() const { return _undo_stack; }
public slots:
void push(UndoCommand *cmd);
void beginMergeSequence(const QString &text);
void endMergeSequence();
public:
void reset();
void doNotMerge();
private:
QUndoStack *_undo_stack;
bool _do_not_merge;
};
}
#endif // QMT_UNDOCONTROLLER_H

View File

@@ -0,0 +1,107 @@
/***************************************************************************
**
** 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 "dannotation.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DAnnotation::DAnnotation()
: DElement(),
_visual_role(ROLE_NORMAL),
_auto_sized(true)
{
}
DAnnotation::DAnnotation(const DAnnotation &rhs)
: DElement(rhs),
_text(rhs._text),
_pos(rhs._pos),
_rect(rhs._rect),
_visual_role(rhs._visual_role),
_auto_sized(rhs._auto_sized)
{
}
DAnnotation::~DAnnotation()
{
}
DAnnotation &DAnnotation::operator=(const DAnnotation &rhs)
{
if (this != &rhs) {
DElement::operator=(rhs);
_text = rhs._text;
_pos = rhs._pos;
_rect = rhs._rect;
_visual_role = rhs._visual_role;
_auto_sized = rhs._auto_sized;
}
return *this;
}
void DAnnotation::setText(const QString &text)
{
_text = text;
}
void DAnnotation::setPos(const QPointF &pos)
{
_pos = pos;
}
void DAnnotation::setRect(const QRectF &rect)
{
_rect = rect;
}
void DAnnotation::setVisualRole(DAnnotation::VisualRole visual_role)
{
_visual_role = visual_role;
}
void DAnnotation::setAutoSize(bool auto_sized)
{
_auto_sized = auto_sized;
}
void DAnnotation::accept(DVisitor *visitor)
{
visitor->visitDAnnotation(this);
}
void DAnnotation::accept(DConstVisitor *visitor) const
{
visitor->visitDAnnotation(this);
}
}

View File

@@ -0,0 +1,113 @@
/***************************************************************************
**
** 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 QMT_DANNOTATION_H
#define QMT_DANNOTATION_H
#include "delement.h"
#include <QPointF>
#include <QRectF>
namespace qmt {
class QMT_EXPORT DAnnotation :
public DElement
{
public:
enum VisualRole {
ROLE_NORMAL,
ROLE_TITLE,
ROLE_SUBTITLE,
ROLE_EMPHASIZED,
ROLE_SOFTEN,
ROLE_FOOTNOTE
};
public:
DAnnotation();
DAnnotation(const DAnnotation &);
~DAnnotation();
public:
DAnnotation &operator=(const DAnnotation &);
public:
Uid getModelUid() const { return Uid::getInvalidUid(); }
QString getText() const { return _text; }
void setText(const QString &text);
QPointF getPos() const { return _pos; }
void setPos(const QPointF &pos);
QRectF getRect() const { return _rect; }
void setRect(const QRectF &rect);
VisualRole getVisualRole() const { return _visual_role; }
void setVisualRole(VisualRole visual_role);
bool hasAutoSize() const { return _auto_sized; }
void setAutoSize(bool auto_sized);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
QString _text;
QPointF _pos;
QRectF _rect;
VisualRole _visual_role;
bool _auto_sized;
};
}
#endif // QMT_DANNOTATION_H

View File

@@ -0,0 +1,121 @@
/***************************************************************************
**
** 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 "dassociation.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DAssociationEnd::DAssociationEnd()
: _kind(MAssociationEnd::ASSOCIATION),
_navigable(false)
{
}
DAssociationEnd::~DAssociationEnd()
{
}
void DAssociationEnd::setName(const QString &name)
{
_name = name;
}
void DAssociationEnd::setCardinatlity(const QString &cardinality)
{
_cardinality = cardinality;
}
void DAssociationEnd::setNavigable(bool navigable)
{
_navigable = navigable;
}
void DAssociationEnd::setKind(MAssociationEnd::Kind kind)
{
_kind = kind;
}
bool operator==(const DAssociationEnd &lhs, const DAssociationEnd &rhs)
{
if (&lhs == &rhs) {
return true;
}
return lhs.getName() == rhs.getName()
&& lhs.getCardinality() == rhs.getCardinality()
&& lhs.getKind() == rhs.getKind()
&& lhs.isNavigable() == rhs.isNavigable();
}
bool operator!=(const DAssociationEnd &lhs, const DAssociationEnd &rhs)
{
return !operator==(lhs, rhs);
}
DAssociation::DAssociation()
: _association_class_uid(Uid::getInvalidUid())
{
}
DAssociation::~DAssociation()
{
}
void DAssociation::setA(const DAssociationEnd &end_a)
{
_end_a = end_a;
}
void DAssociation::setB(const DAssociationEnd &end_b)
{
_end_b = end_b;
}
void DAssociation::setAssociationClassUid(const Uid &uid)
{
_association_class_uid = uid;
}
void DAssociation::accept(DVisitor *visitor)
{
visitor->visitDAssociation(this);
}
void DAssociation::accept(DConstVisitor *visitor) const
{
visitor->visitDAssociation(this);
}
}

View File

@@ -0,0 +1,122 @@
/***************************************************************************
**
** 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 QMT_DASSOCIATION_H
#define QMT_DASSOCIATION_H
#include "drelation.h"
#include "qmt/model/massociation.h"
namespace qmt {
class QMT_EXPORT DAssociationEnd
{
public:
DAssociationEnd();
~DAssociationEnd();
public:
QString getName() const { return _name; }
void setName(const QString &name);
QString getCardinality() const { return _cardinality; }
void setCardinatlity(const QString &cardinality);
MAssociationEnd::Kind getKind() const { return _kind; }
void setKind(MAssociationEnd::Kind kind);
bool isNavigable() const { return _navigable; }
void setNavigable(bool navigable);
private:
QString _name;
QString _cardinality;
MAssociationEnd::Kind _kind;
bool _navigable;
};
bool operator==(const DAssociationEnd &lhs, const DAssociationEnd &rhs);
bool operator!=(const DAssociationEnd &lhs, const DAssociationEnd &rhs);
class QMT_EXPORT DAssociation :
public DRelation
{
public:
DAssociation();
~DAssociation();
public:
DAssociationEnd getA() const { return _end_a; }
void setA(const DAssociationEnd &end_a);
DAssociationEnd getB() const { return _end_b; }
void setB(const DAssociationEnd &end_b);
Uid getAssoicationClassUid() const { return _association_class_uid; }
void setAssociationClassUid(const Uid &uid);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
DAssociationEnd _end_a;
DAssociationEnd _end_b;
Uid _association_class_uid;
};
}
#endif // QMT_DASSOCIATION_H

View File

@@ -0,0 +1,91 @@
/***************************************************************************
**
** 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 "dboundary.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DBoundary::DBoundary()
: DElement()
{
}
DBoundary::DBoundary(const DBoundary &rhs)
: DElement(rhs),
_text(rhs._text),
_pos(rhs._pos),
_rect(rhs._rect)
{
}
DBoundary::~DBoundary()
{
}
DBoundary &DBoundary::operator=(const DBoundary &rhs)
{
if (this != &rhs) {
DElement::operator=(rhs);
_text = rhs._text;
_pos = rhs._pos;
_rect = rhs._rect;
}
return *this;
}
void DBoundary::setText(const QString &text)
{
_text = text;
}
void DBoundary::setPos(const QPointF &pos)
{
_pos = pos;
}
void DBoundary::setRect(const QRectF &rect)
{
_rect = rect;
}
void DBoundary::accept(DVisitor *visitor)
{
visitor->visitDBoundary(this);
}
void DBoundary::accept(DConstVisitor *visitor) const
{
visitor->visitDBoundary(this);
}
}

View File

@@ -0,0 +1,90 @@
/***************************************************************************
**
** 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 QMT_DBOUNDARY_H
#define QMT_DBOUNDARY_H
#include "delement.h"
#include <QPointF>
#include <QRectF>
namespace qmt {
class QMT_EXPORT DBoundary :
public DElement
{
public:
DBoundary();
DBoundary(const DBoundary &rhs);
~DBoundary();
public:
DBoundary &operator=(const DBoundary &rhs);
public:
Uid getModelUid() const { return Uid::getInvalidUid(); }
QString getText() const { return _text; }
void setText(const QString &text);
QPointF getPos() const { return _pos; }
void setPos(const QPointF &pos);
QRectF getRect() const { return _rect; }
void setRect(const QRectF &rect);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
QString _text;
QPointF _pos;
QRectF _rect;
};
}
#endif // QMT_DBOUNDARY_H

View File

@@ -0,0 +1,85 @@
/***************************************************************************
**
** 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 "dclass.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DClass::DClass()
: _template_display(TEMPLATE_SMART),
_show_all_members(false)
{
}
void DClass::setNamespace(const QString &name_space)
{
_namespace = name_space;
}
void DClass::setTemplateParameters(const QList<QString> &template_parameters)
{
_template_parameters = template_parameters;
}
void DClass::setMembers(const QList<MClassMember> &members)
{
_members = members;
}
void DClass::setVisibleMembers(const QSet<Uid> &visible_members)
{
_visible_members = visible_members;
}
void DClass::setTemplateDisplay(DClass::TemplateDisplay template_display)
{
_template_display = template_display;
}
void DClass::setShowAllMembers(bool show_all_members)
{
_show_all_members = show_all_members;
}
void DClass::accept(DVisitor *visitor)
{
visitor->visitDClass(this);
}
void DClass::accept(DConstVisitor *visitor) const
{
visitor->visitDClass(this);
}
}

View File

@@ -0,0 +1,105 @@
/***************************************************************************
**
** 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 QMT_DCLASS_H
#define QMT_DCLASS_H
#include "dobject.h"
#include "qmt/model/mclassmember.h"
#include <QSet>
namespace qmt {
class QMT_EXPORT DClass :
public DObject
{
public:
enum TemplateDisplay {
TEMPLATE_SMART,
TEMPLATE_BOX,
TEMPLATE_NAME
};
public:
DClass();
public:
QString getNamespace() const { return _namespace; }
void setNamespace(const QString &name_space);
QList<QString> getTemplateParameters() const { return _template_parameters; }
void setTemplateParameters(const QList<QString> &template_parameters);
QList<MClassMember> getMembers() const { return _members; }
void setMembers(const QList<MClassMember> &members);
QSet<Uid> getVisibleMembers() const { return _visible_members; }
void setVisibleMembers(const QSet<Uid> &visible_members);
TemplateDisplay getTemplateDisplay() const { return _template_display; }
void setTemplateDisplay(TemplateDisplay template_display);
bool getShowAllMembers() const { return _show_all_members; }
void setShowAllMembers(bool show_all_members);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
QString _namespace;
QList<QString> _template_parameters;
QList<MClassMember> _members;
QSet<Uid> _visible_members;
TemplateDisplay _template_display;
bool _show_all_members;
};
}
#endif // QMT_DCLASS_H

View File

@@ -0,0 +1,60 @@
/***************************************************************************
**
** 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 "dcomponent.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DComponent::DComponent()
: DObject(),
_plain_shape(false)
{
}
void DComponent::setPlainShape(bool plane_shape)
{
_plain_shape = plane_shape;
}
void DComponent::accept(DVisitor *visitor)
{
visitor->visitDComponent(this);
}
void DComponent::accept(DConstVisitor *visitor) const
{
visitor->visitDComponent(this);
}
}

View File

@@ -0,0 +1,64 @@
/***************************************************************************
**
** 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 QMT_DCOMPONENT_H
#define QMT_DCOMPONENT_H
#include "dobject.h"
namespace qmt {
class QMT_EXPORT DComponent :
public DObject
{
public:
DComponent();
public:
bool getPlainShape() const { return _plain_shape; }
void setPlainShape(bool plane_shape);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
bool _plain_shape;
};
}
#endif // QMT_DCOMPONENT_H

View File

@@ -0,0 +1,85 @@
/***************************************************************************
**
** 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 QMT_DCONSTVISITOR_H
#define QMT_DCONSTVISITOR_H
namespace qmt {
class DElement;
class DObject;
class DPackage;
class DClass;
class DComponent;
class DDiagram;
class DItem;
class DRelation;
class DInheritance;
class DDependency;
class DAssociation;
class DAnnotation;
class DBoundary;
class DConstVisitor
{
public:
virtual ~DConstVisitor() { }
virtual void visitDElement(const DElement *element) = 0;
virtual void visitDObject(const DObject *object) = 0;
virtual void visitDPackage(const DPackage *package) = 0;
virtual void visitDClass(const DClass *klass) = 0;
virtual void visitDComponent(const DComponent *component) = 0;
virtual void visitDDiagram(const DDiagram *diagram) = 0;
virtual void visitDItem(const DItem *item) = 0;
virtual void visitDRelation(const DRelation *relation) = 0;
virtual void visitDInheritance(const DInheritance *inheritance) = 0;
virtual void visitDDependency(const DDependency *dependency) = 0;
virtual void visitDAssociation(const DAssociation *association) = 0;
virtual void visitDAnnotation(const DAnnotation *annotation) = 0;
virtual void visitDBoundary(const DBoundary *boundary) = 0;
};
}
#endif // QMT_DCONSTVISITOR_H

View File

@@ -0,0 +1,83 @@
/***************************************************************************
**
** 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 "ddependency.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DDependency::DDependency()
: _direction(MDependency::A_TO_B)
{
}
DDependency::~DDependency()
{
}
Uid DDependency::getSource() const
{
return _direction == MDependency::B_TO_A ? getEndB() : getEndA();
}
void DDependency::setSource(const Uid &source)
{
_direction == MDependency::B_TO_A ? setEndB(source) : setEndA(source);
}
Uid DDependency::getTarget() const
{
return _direction == MDependency::B_TO_A ? getEndA() : getEndB();
}
void DDependency::setTarget(const Uid &target)
{
return _direction == MDependency::B_TO_A ? setEndA(target) : setEndB(target);
}
void DDependency::setDirection(MDependency::Direction direction)
{
_direction = direction;
}
void DDependency::accept(DVisitor *visitor)
{
visitor->visitDDependency(this);
}
void DDependency::accept(DConstVisitor *visitor) const
{
visitor->visitDDependency(this);
}
}

View File

@@ -0,0 +1,80 @@
/***************************************************************************
**
** 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 QMT_DDEPENDENCY_H
#define QMT_DDEPENDENCY_H
#include "drelation.h"
#include "qmt/model/mdependency.h"
namespace qmt {
class DObject;
class QMT_EXPORT DDependency :
public DRelation
{
public:
DDependency();
~DDependency();
public:
Uid getSource() const;
void setSource(const Uid &source);
Uid getTarget() const;
void setTarget(const Uid &target);
MDependency::Direction getDirection() const { return _direction; }
void setDirection(MDependency::Direction direction);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
MDependency::Direction _direction;
};
}
#endif // QMT_DDEPENDENCY_H

View File

@@ -0,0 +1,53 @@
/***************************************************************************
**
** 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 "ddiagram.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DDiagram::DDiagram()
{
}
void DDiagram::accept(DVisitor *visitor)
{
visitor->visitDDiagram(this);
}
void DDiagram::accept(DConstVisitor *visitor) const
{
visitor->visitDDiagram(this);
}
}

View File

@@ -0,0 +1,54 @@
/***************************************************************************
**
** 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 QMT_DDIAGRAM_H
#define QMT_DDIAGRAM_H
#include "dobject.h"
namespace qmt {
class QMT_EXPORT DDiagram :
public DObject
{
public:
DDiagram();
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
};
}
#endif // QMT_DDIAGRAM_H

View File

@@ -0,0 +1,68 @@
/***************************************************************************
**
** 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 "delement.h"
#include "dconstvisitor.h"
#include "dvisitor.h"
namespace qmt {
DElement::DElement()
{
}
DElement::~DElement()
{
}
void DElement::setUid(const Uid &uid)
{
_uid = uid;
}
void DElement::renewUid()
{
_uid.renew();
}
void DElement::accept(DVisitor *visitor)
{
visitor->visitDElement(this);
}
void DElement::accept(DConstVisitor *visitor) const
{
visitor->visitDElement(this);
}
}

View File

@@ -0,0 +1,74 @@
/***************************************************************************
**
** 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 QMT_DELEMENT_H
#define QMT_DELEMENT_H
#include "qmt/infrastructure/uid.h"
#include <QString>
namespace qmt {
class DVisitor;
class DConstVisitor;
class QMT_EXPORT DElement
{
public:
DElement();
virtual ~DElement();
public:
Uid getUid() const { return _uid; }
void setUid(const Uid &uid);
void renewUid();
virtual Uid getModelUid() const = 0;
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
Uid _uid;
};
}
#endif // QMT_DELEMENT_H

View File

@@ -0,0 +1,75 @@
/***************************************************************************
**
** 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 "dinheritance.h"
#include "dclass.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DInheritance::DInheritance()
: DRelation()
{
}
Uid DInheritance::getDerived() const
{
return getEndA();
}
void DInheritance::setDerived(const Uid &derived)
{
setEndA(derived);
}
Uid DInheritance::getBase() const
{
return getEndB();
}
void DInheritance::setBase(const Uid &base)
{
setEndB(base);
}
void DInheritance::accept(DVisitor *visitor)
{
visitor->visitDInheritance(this);
}
void DInheritance::accept(DConstVisitor *visitor) const
{
visitor->visitDInheritance(this);
}
}

View File

@@ -0,0 +1,68 @@
/***************************************************************************
**
** 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 QMT_DINHERITANCE_H
#define QMT_DINHERITANCE_H
#include "drelation.h"
namespace qmt {
class DClass;
class QMT_EXPORT DInheritance :
public DRelation
{
public:
DInheritance();
public:
Uid getDerived() const;
void setDerived(const Uid &derived);
Uid getBase() const;
void setBase(const Uid &base);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
};
}
#endif // QMT_DINHERITANCE_H

View File

@@ -0,0 +1,74 @@
/***************************************************************************
**
** 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 "ditem.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DItem::DItem()
: DObject(),
_shape_editable(true)
{
}
DItem::~DItem()
{
}
void DItem::setVariety(const QString &variety)
{
_variety = variety;
}
void DItem::setShape(const QString &shape)
{
_shape = shape;
}
void DItem::setShapeEditable(bool shape_editable)
{
_shape_editable = shape_editable;
}
void DItem::accept(DVisitor *visitor)
{
visitor->visitDItem(this);
}
void DItem::accept(DConstVisitor *visitor) const
{
visitor->visitDItem(this);
}
} // namespace qmt

View File

@@ -0,0 +1,80 @@
/***************************************************************************
**
** 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 QMT_DITEM_H
#define QMT_DITEM_H
#include "dobject.h"
namespace qmt {
class QMT_EXPORT DItem :
public DObject
{
public:
DItem();
~DItem();
public:
QString getVariety() const { return _variety; }
void setVariety(const QString &variety);
QString getShape() const { return _shape; }
void setShape(const QString &shape);
bool isShapeEditable() const { return _shape_editable; }
void setShapeEditable(bool shape_editable);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
QString _variety;
QString _shape;
bool _shape_editable;
};
} // namespace qmt
#endif // QMT_DITEM_H

View File

@@ -0,0 +1,159 @@
/***************************************************************************
**
** 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 "dobject.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DObject::DObject()
: DElement(),
_model_uid(Uid::getInvalidUid()),
_depth(0),
_visual_primary_role(PRIMARY_ROLE_NORMAL),
_visual_secondary_role(SECONDARY_ROLE_NONE),
_stereotype_display(STEREOTYPE_SMART),
_auto_sized(true),
_visual_emphasized(false)
{
}
DObject::DObject(const DObject &rhs)
: DElement(rhs),
_model_uid(rhs._model_uid),
_context(rhs._context),
_name(rhs._name),
_pos(rhs._pos),
_rect(rhs._rect),
_depth(rhs._depth),
_visual_primary_role(rhs._visual_primary_role),
_visual_secondary_role(rhs._visual_secondary_role),
_stereotype_display(rhs._stereotype_display),
_auto_sized(rhs._auto_sized),
_visual_emphasized(rhs._visual_emphasized)
{
}
DObject::~DObject()
{
}
DObject &DObject::operator =(const DObject &rhs)
{
if (this != &rhs) {
DElement::operator=(rhs);
_model_uid = rhs._model_uid;
_context = rhs._context;
_name = rhs._name;
_pos = rhs._pos;
_rect = rhs._rect;
_depth = rhs._depth;
_visual_primary_role = rhs._visual_primary_role;
_visual_secondary_role = rhs._visual_secondary_role;
_stereotype_display = rhs._stereotype_display;
_auto_sized = rhs._auto_sized;
_visual_emphasized = rhs._visual_emphasized;
}
return *this;
}
void DObject::setModelUid(const Uid &uid)
{
_model_uid = uid;
}
void DObject::setStereotypes(const QList<QString> &stereotypes)
{
_stereotypes = stereotypes;
}
void DObject::setContext(const QString &context)
{
_context = context;
}
void DObject::setName(const QString &name)
{
_name = name;
}
void DObject::setPos(const QPointF &pos)
{
_pos = pos;
}
void DObject::setRect(const QRectF &rect)
{
_rect = rect;
}
void DObject::setDepth(int depth)
{
_depth = depth;
}
void DObject::setVisualPrimaryRole(DObject::VisualPrimaryRole visual_primary_role)
{
_visual_primary_role = visual_primary_role;
}
void DObject::setVisualSecondaryRole(DObject::VisualSecondaryRole visual_secondary_role)
{
_visual_secondary_role = visual_secondary_role;
}
void DObject::setStereotypeDisplay(DObject::StereotypeDisplay stereotype_display)
{
_stereotype_display = stereotype_display;
}
void DObject::setAutoSize(bool auto_sized)
{
_auto_sized = auto_sized;
}
void DObject::setVisualEmphasized(bool visual_emphasized)
{
_visual_emphasized = visual_emphasized;
}
void DObject::accept(DVisitor *visitor)
{
visitor->visitDObject(this);
}
void DObject::accept(DConstVisitor *visitor) const
{
visitor->visitDObject(this);
}
}

View File

@@ -0,0 +1,178 @@
/***************************************************************************
**
** 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 QMT_DOBJECT_H
#define QMT_DOBJECT_H
#include "delement.h"
#include "qmt/infrastructure/uid.h"
#include <QList>
#include <QPointF>
#include <QRectF>
namespace qmt {
class MObject;
class QMT_EXPORT DObject :
public DElement
{
public:
enum VisualPrimaryRole {
PRIMARY_ROLE_NORMAL,
DEPRECATED_PRIMARY_ROLE_LIGHTER,
DEPRECATED_PRIMARY_ROLE_DARKER,
DEPRECATED_PRIMARY_ROLE_SOFTEN,
DEPRECATED_PRIMARY_ROLE_OUTLINE,
PRIMARY_ROLE_CUSTOM1,
PRIMARY_ROLE_CUSTOM2,
PRIMARY_ROLE_CUSTOM3,
PRIMARY_ROLE_CUSTOM4,
PRIMARY_ROLE_CUSTOM5
};
enum VisualSecondaryRole {
SECONDARY_ROLE_NONE,
SECONDARY_ROLE_LIGHTER,
SECONDARY_ROLE_DARKER,
SECONDARY_ROLE_SOFTEN,
SECONDARY_ROLE_OUTLINE
};
enum StereotypeDisplay {
STEREOTYPE_NONE,
STEREOTYPE_LABEL,
STEREOTYPE_DECORATION,
STEREOTYPE_ICON,
STEREOTYPE_SMART
};
public:
DObject();
DObject(const DObject &);
~DObject();
public:
DObject &operator=(const DObject &rhs);
public:
Uid getModelUid() const { return _model_uid; }
void setModelUid(const Uid &uid);
QList<QString> getStereotypes() const { return _stereotypes; }
void setStereotypes(const QList<QString> &stereotypes);
QString getContext() const { return _context; }
void setContext(const QString &context);
QString getName() const { return _name; }
void setName(const QString &name);
QPointF getPos() const { return _pos; }
void setPos(const QPointF &pos);
QRectF getRect() const { return _rect; }
void setRect(const QRectF &rect);
int getDepth() const { return _depth; }
void setDepth(int depth);
VisualPrimaryRole getVisualPrimaryRole() const { return _visual_primary_role; }
void setVisualPrimaryRole(VisualPrimaryRole visual_primary_role);
VisualSecondaryRole getVisualSecondaryRole() const { return _visual_secondary_role; }
void setVisualSecondaryRole(VisualSecondaryRole visual_secondary_role);
StereotypeDisplay getStereotypeDisplay() const { return _stereotype_display; }
void setStereotypeDisplay(StereotypeDisplay stereotype_display);
bool hasAutoSize() const { return _auto_sized; }
void setAutoSize(bool auto_sized);
bool isVisualEmphasized() const { return _visual_emphasized; }
void setVisualEmphasized(bool visual_emphasized);
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
private:
Uid _model_uid;
QList<QString> _stereotypes;
QString _context;
QString _name;
QPointF _pos;
QRectF _rect;
int _depth;
VisualPrimaryRole _visual_primary_role;
VisualSecondaryRole _visual_secondary_role;
StereotypeDisplay _stereotype_display;
bool _auto_sized;
bool _visual_emphasized;
};
}
#endif // QMT_DOBJECT_H

View File

@@ -0,0 +1,53 @@
/***************************************************************************
**
** 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 "dpackage.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DPackage::DPackage()
{
}
void DPackage::accept(DVisitor *visitor)
{
visitor->visitDPackage(this);
}
void DPackage::accept(DConstVisitor *visitor) const
{
visitor->visitDPackage(this);
}
}

View File

@@ -0,0 +1,54 @@
/***************************************************************************
**
** 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 QMT_DPACKAGE_H
#define QMT_DPACKAGE_H
#include "dobject.h"
namespace qmt {
class QMT_EXPORT DPackage :
public DObject
{
public:
DPackage();
public:
virtual void accept(DVisitor *visitor);
virtual void accept(DConstVisitor *visitor) const;
};
}
#endif // QMT_DPACKAGE_H

View File

@@ -0,0 +1,97 @@
/***************************************************************************
**
** 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 "drelation.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DRelation::IntermediatePoint::IntermediatePoint(const QPointF &pos)
: _pos(pos)
{
}
void DRelation::IntermediatePoint::setPos(const QPointF &pos)
{
_pos = pos;
}
bool operator==(const DRelation::IntermediatePoint &lhs, const DRelation::IntermediatePoint &rhs)
{
return lhs.getPos() == rhs.getPos();
}
DRelation::DRelation()
: DElement(),
_model_uid(Uid::getInvalidUid()),
_end_a_uid(Uid::getInvalidUid()),
_end_b_uid(Uid::getInvalidUid())
{
}
DRelation::~DRelation()
{
}
void DRelation::setModelUid(const Uid &uid)
{
_model_uid = uid;
}
void DRelation::setStereotypes(const QList<QString> &stereotypes)
{
_stereotypes = stereotypes;
}
void DRelation::setEndA(const Uid &uid)
{
_end_a_uid = uid;
}
void DRelation::setEndB(const Uid &uid)
{
_end_b_uid = uid;
}
void DRelation::setName(const QString &name)
{
_name = name;
}
void DRelation::setIntermediatePoints(const QList<DRelation::IntermediatePoint> &intermediate_points)
{
_intermediate_points = intermediate_points;
}
}

View File

@@ -0,0 +1,119 @@
/***************************************************************************
**
** 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 QMT_DRELATION_H
#define QMT_DRELATION_H
#include "delement.h"
#include <QList>
#include <QPointF>
namespace qmt {
class DObject;
class QMT_EXPORT DRelation :
public DElement
{
public:
class IntermediatePoint {
public:
explicit IntermediatePoint(const QPointF &pos = QPointF());
QPointF getPos() const { return _pos; }
void setPos(const QPointF &pos);
private:
QPointF _pos;
};
public:
DRelation();
~DRelation();
public:
Uid getModelUid() const { return _model_uid; }
void setModelUid(const Uid &uid);
QList<QString> getStereotypes() const { return _stereotypes; }
void setStereotypes(const QList<QString> &stereotypes);
Uid getEndA() const { return _end_a_uid; }
void setEndA(const Uid &uid);
Uid getEndB() const { return _end_b_uid; }
void setEndB(const Uid &uid);
QString getName() const { return _name; }
void setName(const QString &name);
QList<IntermediatePoint> getIntermediatePoints() const { return _intermediate_points; }
void setIntermediatePoints(const QList<IntermediatePoint> &intermediate_points);
private:
Uid _model_uid;
QList<QString> _stereotypes;
Uid _end_a_uid;
Uid _end_b_uid;
QString _name;
QList<IntermediatePoint> _intermediate_points;
};
bool operator==(const DRelation::IntermediatePoint &lhs, const DRelation::IntermediatePoint &rhs);
inline bool operator!=(const DRelation::IntermediatePoint &lhs, const DRelation::IntermediatePoint &rhs) { return !(lhs == rhs); }
}
#endif // QMT_DRELATION_H

View File

@@ -0,0 +1,84 @@
/***************************************************************************
**
** 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 QMT_DVISITOR_H
#define QMT_DVISITOR_H
namespace qmt {
class DElement;
class DObject;
class DPackage;
class DClass;
class DComponent;
class DDiagram;
class DItem;
class DRelation;
class DInheritance;
class DDependency;
class DAssociation;
class DAnnotation;
class DBoundary;
class DVisitor
{
public:
virtual ~DVisitor() { }
virtual void visitDElement(DElement *element) = 0;
virtual void visitDObject(DObject *object) = 0;
virtual void visitDPackage(DPackage *package) = 0;
virtual void visitDClass(DClass *klass) = 0;
virtual void visitDComponent(DComponent *component) = 0;
virtual void visitDDiagram(DDiagram *diagram) = 0;
virtual void visitDItem(DItem *item) = 0;
virtual void visitDRelation(DRelation *relation) = 0;
virtual void visitDInheritance(DInheritance *inheritance) = 0;
virtual void visitDDependency(DDependency *dependency) = 0;
virtual void visitDAssociation(DAssociation *association) = 0;
virtual void visitDAnnotation(DAnnotation *annotation) = 0;
virtual void visitDBoundary(DBoundary *boundary) = 0;
};
}
#endif // QMT_DVISITOR_H

View File

@@ -0,0 +1,260 @@
/***************************************************************************
**
** 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 "dclonevisitor.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/dpackage.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/dcomponent.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram/ditem.h"
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
DCloneVisitor::DCloneVisitor()
: _cloned(0)
{
}
void DCloneVisitor::visitDElement(const DElement *element)
{
Q_UNUSED(element);
QMT_CHECK(_cloned);
}
void DCloneVisitor::visitDObject(const DObject *object)
{
QMT_CHECK(_cloned);
visitDElement(object);
}
void DCloneVisitor::visitDPackage(const DPackage *package)
{
if (!_cloned) {
_cloned = new DPackage(*package);
}
visitDObject(package);
}
void DCloneVisitor::visitDClass(const DClass *klass)
{
if (!_cloned) {
_cloned = new DClass(*klass);
}
visitDObject(klass);
}
void DCloneVisitor::visitDComponent(const DComponent *component)
{
if (!_cloned) {
_cloned = new DComponent(*component);
}
visitDObject(component);
}
void DCloneVisitor::visitDDiagram(const DDiagram *diagram)
{
if (!_cloned) {
_cloned = new DDiagram(*diagram);
}
visitDObject(diagram);
}
void DCloneVisitor::visitDItem(const DItem *item)
{
if (!_cloned) {
_cloned = new DItem(*item);
}
visitDObject(item);
}
void DCloneVisitor::visitDRelation(const DRelation *relation)
{
QMT_CHECK(_cloned);
visitDElement(relation);
}
void DCloneVisitor::visitDInheritance(const DInheritance *inheritance)
{
if (!_cloned) {
_cloned = new DInheritance(*inheritance);
}
visitDRelation(inheritance);
}
void DCloneVisitor::visitDDependency(const DDependency *dependency)
{
if (!_cloned) {
_cloned = new DDependency(*dependency);
}
visitDRelation(dependency);
}
void DCloneVisitor::visitDAssociation(const DAssociation *association)
{
if (!_cloned) {
_cloned = new DAssociation(*association);
}
visitDRelation(association);
}
void DCloneVisitor::visitDAnnotation(const DAnnotation *annotation)
{
if (!_cloned) {
_cloned = new DAnnotation(*annotation);
}
visitDElement(annotation);
}
void DCloneVisitor::visitDBoundary(const DBoundary *boundary)
{
if (!_cloned) {
_cloned = new DBoundary(*boundary);
}
visitDElement(boundary);
}
DCloneDeepVisitor::DCloneDeepVisitor()
: _cloned(0)
{
}
void DCloneDeepVisitor::visitDElement(const DElement *element)
{
Q_UNUSED(element);
QMT_CHECK(_cloned);
}
void DCloneDeepVisitor::visitDObject(const DObject *object)
{
QMT_CHECK(_cloned);
visitDElement(object);
}
void DCloneDeepVisitor::visitDPackage(const DPackage *package)
{
if (!_cloned) {
_cloned = new DPackage(*package);
}
visitDObject(package);
}
void DCloneDeepVisitor::visitDClass(const DClass *klass)
{
if (!_cloned) {
_cloned = new DClass(*klass);
}
visitDObject(klass);
}
void DCloneDeepVisitor::visitDComponent(const DComponent *component)
{
if (!_cloned) {
_cloned = new DComponent(*component);
}
visitDObject(component);
}
void DCloneDeepVisitor::visitDDiagram(const DDiagram *diagram)
{
if (!_cloned) {
_cloned = new DDiagram(*diagram);
}
visitDObject(diagram);
}
void DCloneDeepVisitor::visitDItem(const DItem *item)
{
if (!_cloned) {
_cloned = new DItem(*item);
}
visitDObject(item);
}
void DCloneDeepVisitor::visitDRelation(const DRelation *relation)
{
QMT_CHECK(_cloned);
visitDElement(relation);
}
void DCloneDeepVisitor::visitDInheritance(const DInheritance *inheritance)
{
if (!_cloned) {
_cloned = new DInheritance(*inheritance);
}
visitDRelation(inheritance);
}
void DCloneDeepVisitor::visitDDependency(const DDependency *dependency)
{
if (!_cloned) {
_cloned = new DDependency(*dependency);
}
visitDRelation(dependency);
}
void DCloneDeepVisitor::visitDAssociation(const DAssociation *association)
{
if (!_cloned) {
_cloned = new DAssociation(*association);
}
visitDRelation(association);
}
void DCloneDeepVisitor::visitDAnnotation(const DAnnotation *annotation)
{
if (!_cloned) {
_cloned = new DAnnotation(*annotation);
}
visitDElement(annotation);
}
void DCloneDeepVisitor::visitDBoundary(const DBoundary *boundary)
{
if (!_cloned) {
_cloned = new DBoundary(*boundary);
}
visitDElement(boundary);
}
}

View File

@@ -0,0 +1,124 @@
/***************************************************************************
**
** 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 QMT_DCLONEVISITOR_H
#define QMT_DCLONEVISITOR_H
#include "qmt/diagram/dconstvisitor.h"
#include "qmt/infrastructure/qmt_global.h"
#include <qglobal.h>
namespace qmt {
class QMT_EXPORT DCloneVisitor :
public DConstVisitor
{
public:
DCloneVisitor();
public:
DElement *getCloned() const { return _cloned; }
void visitDElement(const DElement *element);
void visitDObject(const DObject *object);
void visitDPackage(const DPackage *package);
void visitDClass(const DClass *klass);
void visitDComponent(const DComponent *component);
void visitDDiagram(const DDiagram *diagram);
void visitDItem(const DItem *item);
void visitDRelation(const DRelation *relation);
void visitDInheritance(const DInheritance *inheritance);
void visitDDependency(const DDependency *dependency);
void visitDAssociation(const DAssociation *association);
void visitDAnnotation(const DAnnotation *annotation);
void visitDBoundary(const DBoundary *boundary);
private:
DElement *_cloned;
};
class QMT_EXPORT DCloneDeepVisitor :
public DConstVisitor
{
public:
DCloneDeepVisitor();
public:
DElement *getCloned() const { return _cloned; }
void visitDElement(const DElement *element);
void visitDObject(const DObject *object);
void visitDPackage(const DPackage *package);
void visitDClass(const DClass *klass);
void visitDComponent(const DComponent *component);
void visitDDiagram(const DDiagram *diagram);
void visitDItem(const DItem *item);
void visitDRelation(const DRelation *relation);
void visitDInheritance(const DInheritance *inheritance);
void visitDDependency(const DDependency *dependency);
void visitDAssociation(const DAssociation *association);
void visitDAnnotation(const DAnnotation *annotation);
void visitDBoundary(const DBoundary *boundary);
private:
DElement *_cloned;
};
}
#endif // QMT_DCLONEVISITOR_H

View File

@@ -0,0 +1,47 @@
/***************************************************************************
**
** 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 QMT_DCONTAINER_H
#define QMT_DCONTAINER_H
#include "qmt/controller/container.h"
#include "qmt/diagram/delement.h"
namespace qmt {
class QMT_EXPORT DContainer :
public Container<DElement>
{
};
}
#endif // QMT_DCONTAINER_H

View File

@@ -0,0 +1,158 @@
/***************************************************************************
**
** 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 "dfactory.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/dpackage.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/dcomponent.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram/ditem.h"
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/model/melement.h"
#include "qmt/model/mobject.h"
#include "qmt/model/mclass.h"
#include "qmt/model/mcomponent.h"
#include "qmt/model/mpackage.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/mcanvasdiagram.h"
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
namespace qmt {
DFactory::DFactory()
: _product(0)
{
}
void DFactory::visitMElement(const MElement *element)
{
Q_UNUSED(element);
QMT_CHECK(_product);
}
void DFactory::visitMObject(const MObject *object)
{
DObject *diagram_object = dynamic_cast<DObject *>(_product);
QMT_CHECK(diagram_object);
diagram_object->setModelUid(object->getUid());
visitMElement(object);
}
void DFactory::visitMPackage(const MPackage *package)
{
QMT_CHECK(!_product);
DPackage *diagram_package = new DPackage();
_product = diagram_package;
visitMObject(package);
}
void DFactory::visitMClass(const MClass *klass)
{
QMT_CHECK(!_product);
DClass *diagram_klass = new DClass();
_product = diagram_klass;
visitMObject(klass);
}
void DFactory::visitMComponent(const MComponent *component)
{
QMT_CHECK(!_product);
DComponent *diagram_component = new DComponent();
_product = diagram_component;
visitMObject(component);
}
void DFactory::visitMDiagram(const MDiagram *diagram)
{
QMT_CHECK(!_product);
DDiagram *diagram_diagram = new DDiagram();
_product = diagram_diagram;
visitMObject(diagram);
}
void DFactory::visitMCanvasDiagram(const MCanvasDiagram *diagram)
{
QMT_CHECK(!_product);
visitMDiagram(diagram);
}
void DFactory::visitMItem(const MItem *item)
{
QMT_CHECK(!_product);
DItem *diagram_item = new DItem();
_product = diagram_item;
visitMObject(item);
}
void DFactory::visitMRelation(const MRelation *relation)
{
DRelation *diagram_relation = dynamic_cast<DRelation *>(_product);
QMT_CHECK(diagram_relation);
diagram_relation->setModelUid(relation->getUid());
visitMElement(relation);
}
void DFactory::visitMDependency(const MDependency *dependency)
{
QMT_CHECK(!_product);
DDependency *diagram_dependency = new DDependency();
_product = diagram_dependency;
visitMRelation(dependency);
}
void DFactory::visitMInheritance(const MInheritance *inheritance)
{
QMT_CHECK(!_product);
DInheritance *diagram_inheritance = new DInheritance();
_product = diagram_inheritance;
visitMRelation(inheritance);
}
void DFactory::visitMAssociation(const MAssociation *association)
{
QMT_CHECK(!_product);
DAssociation *diagram_association = new DAssociation();
_product = diagram_association;
visitMRelation(association);
}
}

View File

@@ -0,0 +1,86 @@
/***************************************************************************
**
** 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 QMT_DFACTORY_H
#define QMT_DFACTORY_H
#include "qmt/model/mconstvisitor.h"
#include "qmt/infrastructure/qmt_global.h"
#include <qglobal.h>
namespace qmt {
class DElement;
class QMT_EXPORT DFactory :
public MConstVisitor
{
public:
DFactory();
public:
DElement *getProduct() const { return _product; }
public:
void visitMElement(const MElement *element);
void visitMObject(const MObject *object);
void visitMPackage(const MPackage *package);
void visitMClass(const MClass *klass);
void visitMComponent(const MComponent *component);
void visitMDiagram(const MDiagram *diagram);
void visitMCanvasDiagram(const MCanvasDiagram *diagram);
void visitMItem(const MItem *item);
void visitMRelation(const MRelation *relation);
void visitMDependency(const MDependency *dependency);
void visitMInheritance(const MInheritance *inheritance);
void visitMAssociation(const MAssociation *association);
private:
DElement *_product;
};
}
#endif // QMT_DFACTORY_H

View File

@@ -0,0 +1,172 @@
/***************************************************************************
**
** 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 "dflatassignmentvisitor.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/dpackage.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/dcomponent.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram/ditem.h"
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
// TODO may flat assignment visitor use operator=() ?
DFlatAssignmentVisitor::DFlatAssignmentVisitor(DElement *target)
: _target(target)
{
QMT_CHECK(target);
}
void DFlatAssignmentVisitor::visitDElement(const DElement *element)
{
Q_UNUSED(element);
}
void DFlatAssignmentVisitor::visitDObject(const DObject *object)
{
visitDElement(object);
DObject *target = dynamic_cast<DObject *>(_target);
QMT_CHECK(target);
target->setStereotypes(object->getStereotypes());
target->setName(object->getName());
target->setPos(object->getPos());
target->setRect(object->getRect());
target->setAutoSize(object->hasAutoSize());
target->setDepth(object->getDepth());
target->setVisualPrimaryRole(object->getVisualPrimaryRole());
target->setVisualSecondaryRole(object->getVisualSecondaryRole());
target->setVisualEmphasized(object->isVisualEmphasized());
target->setStereotypeDisplay(object->getStereotypeDisplay());
}
void DFlatAssignmentVisitor::visitDPackage(const DPackage *package)
{
visitDObject(package);
}
void DFlatAssignmentVisitor::visitDClass(const DClass *klass)
{
visitDObject(klass);
DClass *target = dynamic_cast<DClass *>(_target);
QMT_CHECK(target);
target->setNamespace(klass->getNamespace());
target->setTemplateParameters(klass->getTemplateParameters());
target->setTemplateDisplay(klass->getTemplateDisplay());
target->setMembers(klass->getMembers());
target->setShowAllMembers(klass->getShowAllMembers());
target->setVisibleMembers(klass->getVisibleMembers());
}
void DFlatAssignmentVisitor::visitDComponent(const DComponent *component)
{
visitDObject(component);
DComponent *target = dynamic_cast<DComponent *>(_target);
QMT_CHECK(target);
target->setPlainShape(component->getPlainShape());
}
void DFlatAssignmentVisitor::visitDDiagram(const DDiagram *diagram)
{
visitDObject(diagram);
}
void DFlatAssignmentVisitor::visitDItem(const DItem *item)
{
visitDObject(item);
DItem *target = dynamic_cast<DItem *>(_target);
QMT_CHECK(target);
target->setVariety(target->getVariety());
target->setShapeEditable(target->isShapeEditable());
target->setShape(target->getShape());
}
void DFlatAssignmentVisitor::visitDRelation(const DRelation *relation)
{
visitDElement(relation);
DRelation *target = dynamic_cast<DRelation *>(_target);
QMT_CHECK(target);
target->setStereotypes(relation->getStereotypes());
target->setIntermediatePoints(relation->getIntermediatePoints());
}
void DFlatAssignmentVisitor::visitDInheritance(const DInheritance *inheritance)
{
visitDRelation(inheritance);
}
void DFlatAssignmentVisitor::visitDDependency(const DDependency *dependency)
{
visitDRelation(dependency);
DDependency *target = dynamic_cast<DDependency *>(_target);
QMT_CHECK(target);
target->setDirection(dependency->getDirection());
}
void DFlatAssignmentVisitor::visitDAssociation(const DAssociation *association)
{
visitDRelation(association);
DAssociation *target = dynamic_cast<DAssociation *>(_target);
QMT_CHECK(target);
target->setA(association->getA());
target->setB(association->getB());
}
void DFlatAssignmentVisitor::visitDAnnotation(const DAnnotation *annotation)
{
visitDElement(annotation);
DAnnotation *target = dynamic_cast<DAnnotation *>(_target);
target->setText(annotation->getText());
target->setPos(annotation->getPos());
target->setRect(annotation->getRect());
target->setAutoSize(annotation->hasAutoSize());
target->setVisualRole(annotation->getVisualRole());
}
void DFlatAssignmentVisitor::visitDBoundary(const DBoundary *boundary)
{
visitDElement(boundary);
DBoundary *target = dynamic_cast<DBoundary *>(_target);
target->setText(boundary->getText());
target->setPos(boundary->getPos());
target->setRect(boundary->getRect());
}
}

View File

@@ -0,0 +1,82 @@
/***************************************************************************
**
** 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 QMT_DFLATASSIGNMENTVISITOR_H
#define QMT_DFLATASSIGNMENTVISITOR_H
#include "qmt/diagram/dconstvisitor.h"
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class QMT_EXPORT DFlatAssignmentVisitor :
public DConstVisitor
{
public:
DFlatAssignmentVisitor(DElement *target);
public:
void visitDElement(const DElement *element);
void visitDObject(const DObject *object);
void visitDPackage(const DPackage *package);
void visitDClass(const DClass *klass);
void visitDComponent(const DComponent *component);
void visitDDiagram(const DDiagram *diagram);
void visitDItem(const DItem *item);
void visitDRelation(const DRelation *relation);
void visitDInheritance(const DInheritance *inheritance);
void visitDDependency(const DDependency *dependency);
void visitDAssociation(const DAssociation *association);
void visitDAnnotation(const DAnnotation *annotation);
void visitDBoundary(const DBoundary *boundary);
private:
DElement *_target;
};
}
#endif // QMT_DFLATASSIGNMENTVISITOR_H

View File

@@ -0,0 +1,948 @@
/***************************************************************************
**
** 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 "diagramcontroller.h"
#include "dselection.h"
#include "dcontainer.h"
#include "dreferences.h"
#include "dflatassignmentvisitor.h"
#include "dclonevisitor.h"
#include "dupdatevisitor.h"
#include "qmt/model_controller/modelcontroller.h"
#include "qmt/model_controller/mchildrenvisitor.h"
#include "qmt/controller/undocontroller.h"
#include "qmt/controller/undocommand.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/drelation.h"
#include "qmt/model/mobject.h"
#include "qmt/model/mpackage.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/mrelation.h"
namespace qmt {
struct DiagramController::Clone {
Clone();
Uid _element_key;
int _index_of_element;
DElement *_cloned_element;
};
DiagramController::Clone::Clone()
: _index_of_element(-1),
_cloned_element(0)
{
}
class DiagramController::DiagramUndoCommand :
public UndoCommand
{
public:
DiagramUndoCommand(DiagramController *diagram_controller, const Uid &diagram_key, const QString &text)
: UndoCommand(text),
_diagram_controller(diagram_controller),
_diagram_key(diagram_key)
{
}
protected:
DiagramController *getDiagramController() const
{
return _diagram_controller;
}
Uid getDiagramKey() const { return _diagram_key; }
MDiagram *getDiagram() const
{
MDiagram *diagram = _diagram_controller->findDiagram(_diagram_key);
QMT_CHECK(diagram);
return diagram;
}
private:
DiagramController *_diagram_controller;
Uid _diagram_key;
};
class DiagramController::UpdateElementCommand :
public DiagramUndoCommand
{
public:
UpdateElementCommand(DiagramController *diagram_controller, const Uid &diagram_key, DElement *element,
DiagramController::UpdateAction update_action)
: DiagramUndoCommand(diagram_controller, diagram_key, tr("Change")),
_update_action(update_action)
{
DCloneVisitor visitor;
element->accept(&visitor);
_cloned_elements.insert(visitor.getCloned()->getUid(), visitor.getCloned());
}
~UpdateElementCommand()
{
qDeleteAll(_cloned_elements);
}
bool mergeWith(const UndoCommand *other)
{
const UpdateElementCommand *other_update_command = dynamic_cast<const UpdateElementCommand *>(other);
if (!other_update_command) {
return false;
}
if (getDiagramKey() != other_update_command->getDiagramKey()) {
return false;
}
if (_update_action == DiagramController::UPDATE_MAJOR || other_update_command->_update_action == DiagramController::UPDATE_MAJOR
|| _update_action != other_update_command->_update_action) {
return false;
}
// join other elements into this command
foreach (const DElement *other_element, other_update_command->_cloned_elements.values()) {
if (!_cloned_elements.contains(other_element->getUid())) {
DCloneVisitor visitor;
other_element->accept(&visitor);
_cloned_elements.insert(visitor.getCloned()->getUid(), visitor.getCloned());
}
}
// the last update is a complete update of all changes...
return true;
}
void redo()
{
if (canRedo()) {
swap();
UndoCommand::redo();
}
}
void undo()
{
swap();
UndoCommand::undo();
}
private:
void swap()
{
DiagramController *diagram_controller = getDiagramController();
MDiagram *diagram = getDiagram();
foreach (DElement *cloned_element, _cloned_elements) {
DElement *active_element = diagram_controller->findElement(cloned_element->getUid(), diagram);
QMT_CHECK(active_element);
int row = diagram->getDiagramElements().indexOf(active_element);
emit diagram_controller->beginUpdateElement(row, diagram);
// clone active element
DCloneVisitor clone_visitor;
active_element->accept(&clone_visitor);
DElement *new_element = clone_visitor.getCloned();
// reset active element to cloned element
DFlatAssignmentVisitor visitor(active_element);
cloned_element->accept(&visitor);
// replace stored element with new cloned active element
QMT_CHECK(cloned_element->getUid() == new_element->getUid());
_cloned_elements.insert(new_element->getUid(), new_element);
delete cloned_element;
emit diagram_controller->endUpdateElement(row, diagram);
}
diagram_controller->diagramModified(diagram);
}
private:
DiagramController::UpdateAction _update_action;
QHash<Uid, DElement *> _cloned_elements;
};
class DiagramController::AbstractAddRemCommand :
public DiagramUndoCommand
{
protected:
AbstractAddRemCommand(DiagramController *diagram_controller, const Uid &diagram_key, const QString &command_label)
: DiagramUndoCommand(diagram_controller, diagram_key, command_label)
{
}
~AbstractAddRemCommand()
{
foreach (const Clone &clone, _cloned_elements) {
delete clone._cloned_element;
}
}
void remove()
{
DiagramController *diagram_controller = getDiagramController();
MDiagram *diagram = getDiagram();
bool removed = false;
for (int i = 0; i < _cloned_elements.count(); ++i) {
Clone &clone = _cloned_elements[i];
QMT_CHECK(!clone._cloned_element);
DElement *active_element = diagram_controller->findElement(clone._element_key, diagram);
QMT_CHECK(active_element);
clone._index_of_element = diagram->getDiagramElements().indexOf(active_element);
QMT_CHECK(clone._index_of_element >= 0);
emit diagram_controller->beginRemoveElement(clone._index_of_element, diagram);
DCloneDeepVisitor clone_visitor;
active_element->accept(&clone_visitor);
clone._cloned_element = clone_visitor.getCloned();
diagram->removeDiagramElement(active_element);
emit diagram_controller->endRemoveElement(clone._index_of_element, diagram);
removed = true;
}
if (removed) {
diagram_controller->diagramModified(diagram);
}
}
void insert()
{
DiagramController *diagram_controller = getDiagramController();
MDiagram *diagram = getDiagram();
bool inserted = false;
for (int i = _cloned_elements.count() - 1; i >= 0; --i) {
Clone &clone = _cloned_elements[i];
QMT_CHECK(clone._cloned_element);
QMT_CHECK(clone._cloned_element->getUid() == clone._element_key);
emit diagram_controller->beginInsertElement(clone._index_of_element, diagram);
diagram->insertDiagramElement(clone._index_of_element, clone._cloned_element);
clone._cloned_element = 0;
emit diagram_controller->endInsertElement(clone._index_of_element, diagram);
inserted = true;
}
if (inserted) {
diagram_controller->diagramModified(diagram);
}
}
protected:
QList<Clone> _cloned_elements;
};
class DiagramController::AddElementsCommand :
public AbstractAddRemCommand
{
public:
AddElementsCommand(DiagramController *diagram_controller, const Uid &diagram_key, const QString &command_label)
: AbstractAddRemCommand(diagram_controller, diagram_key, command_label)
{
}
void add(const Uid &element_key)
{
Clone clone;
clone._element_key = element_key;
_cloned_elements.append(clone);
}
void redo()
{
if (canRedo()) {
insert();
UndoCommand::redo();
}
}
void undo()
{
remove();
UndoCommand::undo();
}
};
class DiagramController::RemoveElementsCommand :
public AbstractAddRemCommand
{
public:
RemoveElementsCommand(DiagramController *diagram_controller, const Uid &diagram_key, const QString &command_label)
: AbstractAddRemCommand(diagram_controller, diagram_key, command_label)
{
}
void add(DElement *element)
{
Clone clone;
MDiagram *diagram = getDiagram();
clone._element_key = element->getUid();
clone._index_of_element = diagram->getDiagramElements().indexOf(element);
QMT_CHECK(clone._index_of_element >= 0);
DCloneDeepVisitor visitor;
element->accept(&visitor);
clone._cloned_element = visitor.getCloned();
QMT_CHECK(clone._cloned_element);
_cloned_elements.append(clone);
}
void redo()
{
if (canRedo()) {
remove();
UndoCommand::redo();
}
}
void undo()
{
insert();
UndoCommand::undo();
}
};
class DiagramController::FindDiagramsVisitor :
public MChildrenVisitor
{
public:
FindDiagramsVisitor(QList<MDiagram *> *all_diagrams)
: _all_diagrams(all_diagrams)
{
}
void visitMDiagram(MDiagram *diagram)
{
_all_diagrams->append(diagram);
MChildrenVisitor::visitMDiagram(diagram);
}
private:
QList<MDiagram *> *_all_diagrams;
};
DiagramController::DiagramController(QObject *parent)
: QObject(parent),
_model_controller(0),
_undo_controller(0)
{
}
DiagramController::~DiagramController()
{
}
void DiagramController::setModelController(ModelController *model_controller)
{
if (_model_controller) {
disconnect(_model_controller, 0, this, 0);
_model_controller = 0;
}
if (model_controller) {
_model_controller = model_controller;
connect(model_controller, SIGNAL(beginResetModel()), this, SLOT(onBeginResetModel()));
connect(model_controller, SIGNAL(endResetModel()), this, SLOT(onEndResetModel()));
connect(model_controller, SIGNAL(beginUpdateObject(int,const MObject*)), this, SLOT(onBeginUpdateObject(int,const MObject*)));
connect(model_controller, SIGNAL(endUpdateObject(int,const MObject*)), this, SLOT(onEndUpdateObject(int,const MObject*)));
connect(model_controller, SIGNAL(beginInsertObject(int,const MObject*)), this, SLOT(onBeginInsertObject(int,const MObject*)));
connect(model_controller, SIGNAL(endInsertObject(int,const MObject*)), this, SLOT(onEndInsertObject(int,const MObject*)));
connect(model_controller, SIGNAL(beginRemoveObject(int,const MObject*)), this, SLOT(onBeginRemoveObject(int,const MObject*)));
connect(model_controller, SIGNAL(endRemoveObject(int,const MObject*)), this, SLOT(onEndRemoveObject(int,const MObject*)));
connect(model_controller, SIGNAL(beginMoveObject(int,const MObject*)), this, SLOT(onBeginMoveObject(int,const MObject*)));
connect(model_controller, SIGNAL(endMoveObject(int,const MObject*)), this, SLOT(onEndMoveObject(int,const MObject*)));
connect(model_controller, SIGNAL(beginUpdateRelation(int,const MObject*)), this, SLOT(onBeginUpdateRelation(int,const MObject*)));
connect(model_controller, SIGNAL(endUpdateRelation(int,const MObject*)), this, SLOT(onEndUpdateRelation(int,const MObject*)));
connect(model_controller, SIGNAL(beginRemoveRelation(int,const MObject*)), this, SLOT(onBeginRemoveRelation(int,const MObject*)));
connect(model_controller, SIGNAL(endRemoveRelation(int,const MObject*)), this, SLOT(onEndRemoveRelation(int,const MObject*)));
connect(model_controller, SIGNAL(beginMoveRelation(int,const MObject*)), this, SLOT(onBeginMoveRelation(int,const MObject*)));
connect(model_controller, SIGNAL(endMoveRelation(int,const MObject*)), this, SLOT(onEndMoveRelation(int,const MObject*)));
}
}
void DiagramController::setUndoController(UndoController *undo_controller)
{
_undo_controller = undo_controller;
}
MDiagram *DiagramController::findDiagram(const Uid &diagram_key) const
{
return dynamic_cast<MDiagram *>(_model_controller->findObject(diagram_key));
}
void DiagramController::addElement(DElement *element, MDiagram *diagram)
{
int row = diagram->getDiagramElements().count();
emit beginInsertElement(row, diagram);
updateElementFromModel(element, diagram, false);
if (_undo_controller) {
AddElementsCommand *undo_command = new AddElementsCommand(this, diagram->getUid(), tr("Add Object"));
_undo_controller->push(undo_command);
undo_command->add(element->getUid());
}
diagram->addDiagramElement(element);
emit endInsertElement(row, diagram);
diagramModified(diagram);
}
void DiagramController::removeElement(DElement *element, MDiagram *diagram)
{
removeRelations(element, diagram);
int row = diagram->getDiagramElements().indexOf(element);
emit beginRemoveElement(row, diagram);
if (_undo_controller) {
RemoveElementsCommand *undo_command = new RemoveElementsCommand(this, diagram->getUid(), tr("Remove Object"));
_undo_controller->push(undo_command);
undo_command->add(element);
}
diagram->removeDiagramElement(element);
emit endRemoveElement(row, diagram);
diagramModified(diagram);
}
DElement *DiagramController::findElement(const Uid &key, const MDiagram *diagram) const
{
QMT_CHECK(diagram);
return diagram->findDiagramElement(key);
}
bool DiagramController::hasDelegate(const MElement *model_element, const MDiagram *diagram) const
{
// PERFORM smarter implementation after map is introduced
return findDelegate(model_element, diagram) != 0;
}
DElement *DiagramController::findDelegate(const MElement *model_element, const MDiagram *diagram) const
{
Q_UNUSED(diagram);
// PERFORM use map to increase performance
foreach (DElement *diagram_element, diagram->getDiagramElements()) {
if (diagram_element->getModelUid().isValid() && diagram_element->getModelUid() == model_element->getUid()) {
return diagram_element;
}
}
return 0;
}
void DiagramController::startUpdateElement(DElement *element, MDiagram *diagram, UpdateAction update_action)
{
emit beginUpdateElement(diagram->getDiagramElements().indexOf(element), diagram);
if (_undo_controller) {
_undo_controller->push(new UpdateElementCommand(this, diagram->getUid(), element, update_action));
}
}
void DiagramController::finishUpdateElement(DElement *element, MDiagram *diagram, bool cancelled)
{
if (!cancelled) {
updateElementFromModel(element, diagram, false);
}
emit endUpdateElement(diagram->getDiagramElements().indexOf(element), diagram);
if (!cancelled) {
diagramModified(diagram);
}
}
void DiagramController::breakUndoChain()
{
_undo_controller->doNotMerge();
}
DContainer DiagramController::cutElements(const DSelection &diagram_selection, MDiagram *diagram)
{
DContainer copied_elements = copyElements(diagram_selection, diagram);
deleteElements(diagram_selection, diagram, tr("Cut"));
return copied_elements;
}
DContainer DiagramController::copyElements(const DSelection &diagram_selection, const MDiagram *diagram)
{
QMT_CHECK(diagram);
DReferences simplified_selection = simplify(diagram_selection, diagram);
DContainer copied_elements;
foreach (const DElement *element, simplified_selection.getElements()) {
DCloneDeepVisitor visitor;
element->accept(&visitor);
DElement *cloned_element = visitor.getCloned();
copied_elements.submit(cloned_element);
}
return copied_elements;
}
void DiagramController::pasteElements(const DContainer &diagram_container, MDiagram *diagram)
{
QMT_CHECK(diagram);
// clone all elements and renew their keys
QHash<Uid, Uid> renewed_keys;
QList<DElement *> cloned_elements;
foreach (const DElement *element, diagram_container.getElements()) {
if (!isDelegatedElementOnDiagram(element, diagram)) {
DCloneDeepVisitor visitor;
element->accept(&visitor);
DElement *cloned_element = visitor.getCloned();
renewElementKey(cloned_element, &renewed_keys);
cloned_elements.append(cloned_element);
}
}
// fix all keys referencing between pasting elements
foreach(DElement *cloned_element, cloned_elements) {
DRelation *relation = dynamic_cast<DRelation *>(cloned_element);
if (relation) {
updateRelationKeys(relation, renewed_keys);
}
}
if (_undo_controller) {
_undo_controller->beginMergeSequence(tr("Paste"));
}
// insert all elements
bool added = false;
foreach (DElement *cloned_element, cloned_elements) {
if (!dynamic_cast<DRelation *>(cloned_element)) {
int row = diagram->getDiagramElements().size();
emit beginInsertElement(row, diagram);
if (_undo_controller) {
AddElementsCommand *undo_command = new AddElementsCommand(this, diagram->getUid(), tr("Paste"));
_undo_controller->push(undo_command);
undo_command->add(cloned_element->getUid());
}
diagram->addDiagramElement(cloned_element);
emit endInsertElement(row, diagram);
added = true;
}
}
foreach (DElement *cloned_element, cloned_elements) {
DRelation *cloned_relation = dynamic_cast<DRelation *>(cloned_element);
if (cloned_relation && areRelationEndsOnDiagram(cloned_relation, diagram)) {
int row = diagram->getDiagramElements().size();
emit beginInsertElement(row, diagram);
if (_undo_controller) {
AddElementsCommand *undo_command = new AddElementsCommand(this, diagram->getUid(), tr("Paste"));
_undo_controller->push(undo_command);
undo_command->add(cloned_element->getUid());
}
diagram->addDiagramElement(cloned_element);
emit endInsertElement(row, diagram);
added = true;
}
}
if (added) {
diagramModified(diagram);
}
if (_undo_controller) {
_undo_controller->endMergeSequence();
}
}
void DiagramController::deleteElements(const DSelection &diagram_selection, MDiagram *diagram)
{
deleteElements(diagram_selection, diagram, tr("Delete"));
}
void DiagramController::onBeginResetModel()
{
_all_diagrams.clear();
emit beginResetAllDiagrams();
}
void DiagramController::onEndResetModel()
{
updateAllDiagramsList();
foreach (MDiagram *diagram, _all_diagrams) {
// remove all elements which are not longer part of the model
foreach (DElement *element, diagram->getDiagramElements()) {
if (element->getModelUid().isValid()) {
MElement *model_element = _model_controller->findElement(element->getModelUid());
if (!model_element) {
removeElement(element, diagram);
}
}
}
// update all remaining elements from model
foreach (DElement *element, diagram->getDiagramElements()) {
updateElementFromModel(element, diagram, false);
}
}
emit endResetAllDiagrams();
}
void DiagramController::onBeginUpdateObject(int row, const MObject *parent)
{
Q_UNUSED(row);
Q_UNUSED(parent);
// nothing to do
}
void DiagramController::onEndUpdateObject(int row, const MObject *parent)
{
MObject *model_object = _model_controller->getObject(row, parent);
QMT_CHECK(model_object);
MPackage *model_package = dynamic_cast<MPackage *>(model_object);
foreach (MDiagram *diagram, _all_diagrams) {
DObject *object = findDelegate<DObject>(model_object, diagram);
if (object) {
updateElementFromModel(object, diagram, true);
}
if (model_package) {
// update each element that has the updated object as its owner (for context changes)
foreach (DElement *diagram_element, diagram->getDiagramElements()) {
if (diagram_element->getModelUid().isValid()) {
MObject *mobject = _model_controller->findObject(diagram_element->getModelUid());
if (mobject && mobject->getOwner() == model_package) {
updateElementFromModel(diagram_element, diagram, true);
}
}
}
}
}
}
void DiagramController::onBeginInsertObject(int row, const MObject *owner)
{
Q_UNUSED(row);
Q_UNUSED(owner);
}
void DiagramController::onEndInsertObject(int row, const MObject *owner)
{
QMT_CHECK(owner);
MObject *model_object = _model_controller->getObject(row, owner);
if (MDiagram *model_diagram = dynamic_cast<MDiagram *>(model_object)) {
QMT_CHECK(!_all_diagrams.contains(model_diagram));
_all_diagrams.append(model_diagram);
}
}
void DiagramController::onBeginRemoveObject(int row, const MObject *parent)
{
QMT_CHECK(parent);
MObject *model_object = _model_controller->getObject(row, parent);
removeObjects(model_object);
}
void DiagramController::onEndRemoveObject(int row, const MObject *parent)
{
Q_UNUSED(row);
Q_UNUSED(parent);
}
void DiagramController::onBeginMoveObject(int former_row, const MObject *former_owner)
{
Q_UNUSED(former_row);
Q_UNUSED(former_owner);
}
void DiagramController::onEndMoveObject(int row, const MObject *owner)
{
onEndUpdateObject(row, owner);
// if diagram was moved update all elements because of changed context
MObject *model_object = _model_controller->getObject(row, owner);
QMT_CHECK(model_object);
MDiagram *model_diagram = dynamic_cast<MDiagram *>(model_object);
if (model_diagram) {
emit beginResetDiagram(model_diagram);
foreach (DElement *diagram_element, model_diagram->getDiagramElements()) {
updateElementFromModel(diagram_element, model_diagram, false);
}
emit endResetDiagram(model_diagram);
}
}
void DiagramController::onBeginUpdateRelation(int row, const MObject *owner)
{
Q_UNUSED(row);
Q_UNUSED(owner);
// nothing to do
}
void DiagramController::onEndUpdateRelation(int row, const MObject *owner)
{
MRelation *model_relation = owner->getRelations().at(row);
foreach (MDiagram *diagram, _all_diagrams) {
DRelation *relation = findDelegate<DRelation>(model_relation, diagram);
if (relation) {
updateElementFromModel(relation, diagram, true);
}
}
}
void DiagramController::onBeginRemoveRelation(int row, const MObject *owner)
{
QMT_CHECK(owner);
MRelation *model_relation = owner->getRelations().at(row);
removeRelations(model_relation);
}
void DiagramController::onEndRemoveRelation(int row, const MObject *owner)
{
Q_UNUSED(row);
Q_UNUSED(owner);
}
void DiagramController::onBeginMoveRelation(int former_row, const MObject *former_owner)
{
Q_UNUSED(former_row);
Q_UNUSED(former_owner);
// nothing to do
}
void DiagramController::onEndMoveRelation(int row, const MObject *owner)
{
onEndUpdateRelation(row, owner);
}
void DiagramController::deleteElements(const DSelection &diagram_selection, MDiagram *diagram, const QString &command_label)
{
QMT_CHECK(diagram);
DReferences simplified_selection = simplify(diagram_selection, diagram);
if (simplified_selection.getElements().isEmpty()) {
return;
}
if (_undo_controller) {
_undo_controller->beginMergeSequence(command_label);
}
bool removed = false;
foreach (DElement *element, simplified_selection.getElements()) {
// element may have been deleted indirectly by predecessor element in loop
if ((element = findElement(element->getUid(), diagram))) {
removeRelations(element, diagram);
int row = diagram->getDiagramElements().indexOf(element);
emit beginRemoveElement(diagram->getDiagramElements().indexOf(element), diagram);
if (_undo_controller) {
RemoveElementsCommand *cut_command = new RemoveElementsCommand(this, diagram->getUid(), command_label);
_undo_controller->push(cut_command);
cut_command->add(element);
}
diagram->removeDiagramElement(element);
emit endRemoveElement(row, diagram);
removed = true;
}
}
if (removed) {
diagramModified(diagram);
}
if (_undo_controller) {
_undo_controller->endMergeSequence();
}
}
DElement *DiagramController::findElementOnAnyDiagram(const Uid &uid)
{
foreach (MDiagram *diagram, _all_diagrams) {
DElement *element = findElement(uid, diagram);
if (element) {
return element;
}
}
return 0;
}
void DiagramController::removeObjects(MObject *model_object)
{
foreach (MDiagram *diagram, _all_diagrams) {
DElement *diagram_element = findDelegate(model_object, diagram);
if (diagram_element) {
removeElement(diagram_element, diagram);
}
foreach (const Handle<MRelation> &relation, model_object->getRelations()) {
DElement *diagram_element = findDelegate(relation.getTarget(), diagram);
if (diagram_element) {
removeElement(diagram_element, diagram);
}
}
}
foreach (const Handle<MObject> &object, model_object->getChildren()) {
if (object.hasTarget()) {
removeObjects(object.getTarget());
}
}
if (MDiagram *diagram = dynamic_cast<MDiagram *>(model_object)) {
emit diagramAboutToBeRemoved(diagram);
QMT_CHECK(_all_diagrams.contains(diagram));
_all_diagrams.removeOne(diagram);
QMT_CHECK(!_all_diagrams.contains(diagram));
// PERFORM increase performace
while (!diagram->getDiagramElements().isEmpty()) {
DElement *element = diagram->getDiagramElements().first();
removeElement(element, diagram);
}
}
}
void DiagramController::removeRelations(MRelation *model_relation)
{
foreach (MDiagram *diagram, _all_diagrams) {
DElement *diagram_element = findDelegate(model_relation, diagram);
if (diagram_element) {
removeElement(diagram_element, diagram);
}
}
}
void DiagramController::removeRelations(DElement *element, MDiagram *diagram)
{
DObject *diagram_object = dynamic_cast<DObject *>(element);
if (diagram_object) {
foreach (DElement *diagram_element, diagram->getDiagramElements()) {
if (DRelation *diagram_relation = dynamic_cast<DRelation *>(diagram_element)) {
if (diagram_relation->getEndA() == diagram_object->getUid() || diagram_relation->getEndB() == diagram_object->getUid()) {
removeElement(diagram_relation, diagram);
}
}
}
}
}
void DiagramController::renewElementKey(DElement *element, QHash<Uid, Uid> *renewed_keys)
{
QMT_CHECK(renewed_keys);
if (element) {
DElement *existing_element_on_diagram = findElementOnAnyDiagram(element->getUid());
if (existing_element_on_diagram) {
QMT_CHECK(existing_element_on_diagram != element);
Uid old_key = element->getUid();
element->renewUid();
Uid new_key = element->getUid();
renewed_keys->insert(old_key, new_key);
}
}
}
void DiagramController::updateRelationKeys(DRelation *relation, const QHash<Uid, Uid> &renewed_keys)
{
Uid new_end_a_key = renewed_keys.value(relation->getEndA(), Uid::getInvalidUid());
if (new_end_a_key.isValid()) {
relation->setEndA(new_end_a_key);
}
Uid new_end_b_key = renewed_keys.value(relation->getEndB(), Uid::getInvalidUid());
if (new_end_b_key.isValid()) {
relation->setEndB(new_end_b_key);
}
}
void DiagramController::updateElementFromModel(DElement *element, const MDiagram *diagram, bool emit_update_signal)
{
if (!element->getModelUid().isValid()) {
return;
}
DUpdateVisitor visitor(element, diagram);
MElement *melement = _model_controller->findElement(element->getModelUid());
QMT_CHECK(melement);
if (emit_update_signal) {
visitor.setCheckNeedsUpdate(true);
melement->accept(&visitor);
if (visitor.updateNeeded()) {
int row = diagram->getDiagramElements().indexOf(element);
emit beginUpdateElement(row, diagram);
visitor.setCheckNeedsUpdate(false);
melement->accept(&visitor);
emit endUpdateElement(row, diagram);
}
} else {
melement->accept(&visitor);
}
}
void DiagramController::diagramModified(MDiagram *diagram)
{
// the modification date is updated intentionally without signalling model controller avoiding recursive change updates
diagram->setLastModifiedToNow();
emit modified(diagram);
}
DReferences DiagramController::simplify(const DSelection &diagram_selection, const MDiagram *diagram)
{
DReferences references;
foreach (const DSelection::Index &index, diagram_selection.getIndices()) {
DElement *element = findElement(index.getElementKey(), diagram);
if (element) {
references.append(element);
}
}
return references;
}
MElement *DiagramController::getDelegatedElement(const DElement *element) const
{
if (!element->getModelUid().isValid()) {
return 0;
}
return _model_controller->findElement(element->getModelUid());
}
bool DiagramController::isDelegatedElementOnDiagram(const DElement *element, const MDiagram *diagram) const
{
MElement *model_element = getDelegatedElement(element);
if (!model_element) {
return false;
}
return hasDelegate(model_element, diagram);
}
bool DiagramController::areRelationEndsOnDiagram(const DRelation *relation, const MDiagram *diagram) const
{
return findElement(relation->getEndA(), diagram) && findElement(relation->getEndB(), diagram);
}
void DiagramController::updateAllDiagramsList()
{
_all_diagrams.clear();
if (_model_controller && _model_controller->getRootPackage()) {
FindDiagramsVisitor visitor(&_all_diagrams);
_model_controller->getRootPackage()->accept(&visitor);
}
}
}

View File

@@ -0,0 +1,241 @@
/***************************************************************************
**
** 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 QMT_DIAGRAMCONTROLLER_H
#define QMT_DIAGRAMCONTROLLER_H
#include "qmt/infrastructure/uid.h"
#include <QObject>
#include <QHash>
namespace qmt {
class UndoController;
class ModelController;
class MElement;
class MObject;
class MDiagram;
class MRelation;
class DSelection;
class DContainer;
class DReferences;
class DElement;
class DRelation;
class QMT_EXPORT DiagramController :
public QObject
{
Q_OBJECT
public:
enum UpdateAction {
UPDATE_GEOMETRY, // update only position and size of element
UPDATE_MAJOR, // a major update of the element which will create a separate undo command
UPDATE_MINOR // a minor update of the element which may be merged with other minor updates in one undo command
};
private:
struct Clone;
class DiagramUndoCommand;
class UpdateElementCommand;
class AbstractAddRemCommand;
class AddElementsCommand;
class RemoveElementsCommand;
class FindDiagramsVisitor;
public:
explicit DiagramController(QObject *parent = 0);
~DiagramController();
signals:
void beginResetAllDiagrams();
void endResetAllDiagrams();
void beginResetDiagram(const MDiagram *diagram);
void endResetDiagram(const MDiagram *diagram);
void beginUpdateElement(int row, const MDiagram *diagram);
void endUpdateElement(int row, const MDiagram *diagram);
void beginInsertElement(int row, const MDiagram *diagram);
void endInsertElement(int row, const MDiagram *diagram);
void beginRemoveElement(int row, const MDiagram *diagram);
void endRemoveElement(int row, const MDiagram *diagram);
void modified(const MDiagram *diagram);
void diagramAboutToBeRemoved(const MDiagram *diagram);
public:
ModelController *getModelController() const { return _model_controller; }
void setModelController(ModelController *model_controller);
UndoController *getUndoController() const { return _undo_controller; }
void setUndoController(UndoController *undo_controller);
private:
MDiagram *findDiagram(const Uid &diagram_key) const;
public:
void addElement(DElement *element, MDiagram *diagram);
void removeElement(DElement *element, MDiagram *diagram);
DElement *findElement(const Uid &key, const MDiagram *diagram) const;
template<class T>
T *findElement(const Uid &key, const MDiagram *diagram) const { return dynamic_cast<T *>(findElement(key, diagram)); }
bool hasDelegate(const MElement *model_element, const MDiagram *diagram) const;
DElement *findDelegate(const MElement *model_element, const MDiagram *diagram) const;
template<class T>
T *findDelegate(const MElement *model_element, const MDiagram *diagram) const
{
return dynamic_cast<T *>(findDelegate(model_element, diagram));
}
void startUpdateElement(DElement *element, MDiagram *diagram, UpdateAction update_action);
void finishUpdateElement(DElement *element, MDiagram *diagram, bool cancelled);
void breakUndoChain();
public:
DContainer cutElements(const DSelection &diagram_selection, MDiagram *diagram);
DContainer copyElements(const DSelection &diagram_selection, const MDiagram *diagram);
void pasteElements(const DContainer &diagram_container, MDiagram *diagram);
void deleteElements(const DSelection &diagram_selection, MDiagram *diagram);
private slots:
void onBeginResetModel();
void onEndResetModel();
void onBeginUpdateObject(int row, const MObject *parent);
void onEndUpdateObject(int row, const MObject *parent);
void onBeginInsertObject(int row, const MObject *owner);
void onEndInsertObject(int row, const MObject *owner);
void onBeginRemoveObject(int row, const MObject *parent);
void onEndRemoveObject(int row, const MObject *parent);
void onBeginMoveObject(int former_row, const MObject *former_owner);
void onEndMoveObject(int row, const MObject *owner);
void onBeginUpdateRelation(int row, const MObject *owner);
void onEndUpdateRelation(int row, const MObject *owner);
void onBeginRemoveRelation(int row, const MObject *owner);
void onEndRemoveRelation(int row, const MObject *owner);
void onBeginMoveRelation(int former_row, const MObject *former_owner);
void onEndMoveRelation(int row, const MObject *owner);
private:
void deleteElements(const DSelection &diagram_selection, MDiagram *diagram, const QString &command_label);
DElement *findElementOnAnyDiagram(const Uid &uid);
void removeObjects(MObject *model_object);
void removeRelations(MRelation *model_relation);
void removeRelations(DElement *element, MDiagram *diagram);
void renewElementKey(DElement *element, QHash<Uid, Uid> *renewed_keys);
void updateRelationKeys(DRelation *relation, const QHash<Uid, Uid> &renewed_keys);
void updateElementFromModel(DElement *element, const MDiagram *diagram, bool emit_update_signal);
void diagramModified(MDiagram *diagram);
DReferences simplify(const DSelection &diagram_selection, const MDiagram *diagram);
MElement *getDelegatedElement(const DElement *element) const;
bool isDelegatedElementOnDiagram(const DElement *element, const MDiagram *diagram) const;
bool areRelationEndsOnDiagram(const DRelation *relation, const MDiagram *diagram) const;
void updateAllDiagramsList();
private:
ModelController *_model_controller;
UndoController *_undo_controller;
QList<MDiagram *> _all_diagrams;
};
}
#endif // DIAGRAMCONTROLLER_H

View File

@@ -0,0 +1,49 @@
/***************************************************************************
**
** 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 QMT_DREFERENCES_H
#define QMT_DREFERENCES_H
#include "qmt/controller/references.h"
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class DElement;
class QMT_EXPORT DReferences :
public References<DElement>
{
};
}
#endif // QMT_DREFERENCES_H

View File

@@ -0,0 +1,47 @@
/***************************************************************************
**
** 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 QMT_DSELECTION_H
#define QMT_DSELECTION_H
#include "qmt/controller/selection.h"
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class QMT_EXPORT DSelection :
public Selection
{
};
}
#endif // QMT_DSELECTION_H

View File

@@ -0,0 +1,224 @@
/***************************************************************************
**
** 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 "dupdatevisitor.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/ditem.h"
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/model/melement.h"
#include "qmt/model/mobject.h"
#include "qmt/model/mclass.h"
#include "qmt/model/mcomponent.h"
#include "qmt/model/mpackage.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/mcanvasdiagram.h"
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
namespace qmt {
DUpdateVisitor::DUpdateVisitor(DElement *target, const MDiagram *diagram, bool check_needs_update)
: _target(target),
_diagram(diagram),
_check_needs_update(check_needs_update),
_update_needed(!check_needs_update)
{
}
void DUpdateVisitor::setCheckNeedsUpdate(bool check_needs_update)
{
_check_needs_update = check_needs_update;
_update_needed = !check_needs_update;
}
void DUpdateVisitor::visitMElement(const MElement *element)
{
Q_UNUSED(element);
QMT_CHECK(_target);
}
void DUpdateVisitor::visitMObject(const MObject *object)
{
DObject *dobject = dynamic_cast<DObject *>(_target);
QMT_CHECK(dobject);
if (isUpdating(object->getStereotypes() != dobject->getStereotypes())) {
dobject->setStereotypes(object->getStereotypes());
}
const MObject *object_owner = object->getOwner();
const MObject *diagram_owner = _diagram->getOwner();
if (object_owner && diagram_owner && object_owner->getUid() != diagram_owner->getUid()) {
if (isUpdating(object_owner->getName() != dobject->getContext())) {
dobject->setContext(object_owner->getName());
}
} else {
if (isUpdating(!dobject->getContext().isEmpty())) {
dobject->setContext(QString());
}
}
if (isUpdating(object->getName() != dobject->getName())) {
dobject->setName(object->getName());
}
// TODO unlikely that this is called for all objects if hierarchy is modified
// PERFORM remove loop
int depth = 1;
const MObject *owner = object->getOwner();
while (owner) {
owner = owner->getOwner();
depth += 1;
}
if (isUpdating(depth != dobject->getDepth())) {
dobject->setDepth(depth);
}
visitMElement(object);
}
void DUpdateVisitor::visitMPackage(const MPackage *package)
{
visitMObject(package);
}
void DUpdateVisitor::visitMClass(const MClass *klass)
{
DClass *dclass = dynamic_cast<DClass *>(_target);
QMT_CHECK(dclass);
if (isUpdating(klass->getNamespace() != dclass->getNamespace())) {
dclass->setNamespace(klass->getNamespace());
}
if (isUpdating(klass->getTemplateParameters() != dclass->getTemplateParameters())) {
dclass->setTemplateParameters(klass->getTemplateParameters());
}
if (isUpdating(klass->getMembers() != dclass->getMembers())) {
dclass->setMembers(klass->getMembers());
}
visitMObject(klass);
}
void DUpdateVisitor::visitMComponent(const MComponent *component)
{
visitMObject(component);
}
void DUpdateVisitor::visitMDiagram(const MDiagram *diagram)
{
visitMObject(diagram);
}
void DUpdateVisitor::visitMCanvasDiagram(const MCanvasDiagram *diagram)
{
visitMDiagram(diagram);
}
void DUpdateVisitor::visitMItem(const MItem *item)
{
DItem *ditem = dynamic_cast<DItem *>(_target);
QMT_CHECK(ditem);
if (isUpdating(item->isShapeEditable() != ditem->isShapeEditable())) {
ditem->setShapeEditable(item->isShapeEditable());
}
if (isUpdating(item->getVariety() != ditem->getVariety())) {
ditem->setVariety(item->getVariety());
}
visitMObject(item);
}
void DUpdateVisitor::visitMRelation(const MRelation *relation)
{
DRelation *drelation = dynamic_cast<DRelation *>(_target);
QMT_CHECK(drelation);
if (isUpdating(relation->getStereotypes() != drelation->getStereotypes())) {
drelation->setStereotypes(relation->getStereotypes());
}
if (isUpdating(relation->getName() != drelation->getName())) {
drelation->setName(relation->getName());
}
visitMElement(relation);
}
void DUpdateVisitor::visitMDependency(const MDependency *dependency)
{
DDependency *ddependency = dynamic_cast<DDependency *>(_target);
QMT_CHECK(ddependency);
if (isUpdating(dependency->getDirection() != ddependency->getDirection())) {
ddependency->setDirection(dependency->getDirection());
}
visitMRelation(dependency);
}
void DUpdateVisitor::visitMInheritance(const MInheritance *inheritance)
{
visitMRelation(inheritance);
}
void DUpdateVisitor::visitMAssociation(const MAssociation *association)
{
DAssociation *dassociation = dynamic_cast<DAssociation *>(_target);
QMT_CHECK(dassociation);
DAssociationEnd end_a;
end_a.setName(association->getA().getName());
end_a.setCardinatlity(association->getA().getCardinality());
end_a.setNavigable(association->getA().isNavigable());
end_a.setKind(association->getA().getKind());
if (isUpdating(end_a != dassociation->getA())) {
dassociation->setA(end_a);
}
DAssociationEnd end_b;
end_b.setName(association->getB().getName());
end_b.setCardinatlity(association->getB().getCardinality());
end_b.setNavigable(association->getB().isNavigable());
end_b.setKind(association->getB().getKind());
if (isUpdating(end_b != dassociation->getB())) {
dassociation->setB(end_b);
}
visitMRelation(association);
}
bool DUpdateVisitor::isUpdating(bool value_changed)
{
if (_check_needs_update) {
if (value_changed) {
_update_needed = true;
}
return false;
}
return value_changed;
}
}

View File

@@ -0,0 +1,96 @@
/***************************************************************************
**
** 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 QMT_DUPDATEVISITOR_H
#define QMT_DUPDATEVISITOR_H
#include "qmt/model/mconstvisitor.h"
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class DElement;
class QMT_EXPORT DUpdateVisitor :
public MConstVisitor
{
public:
DUpdateVisitor(DElement *target, const MDiagram *diagram, bool check_needs_update = false);
public:
bool updateNeeded() const { return _update_needed; }
void setCheckNeedsUpdate(bool check_needs_update);
void visitMElement(const MElement *element);
void visitMObject(const MObject *object);
void visitMPackage(const MPackage *package);
void visitMClass(const MClass *klass);
void visitMComponent(const MComponent *component);
void visitMDiagram(const MDiagram *diagram);
void visitMCanvasDiagram(const MCanvasDiagram *diagram);
void visitMItem(const MItem *item);
void visitMRelation(const MRelation *relation);
void visitMDependency(const MDependency *dependency);
void visitMInheritance(const MInheritance *inheritance);
void visitMAssociation(const MAssociation *association);
private:
bool isUpdating(bool value_changed);
private:
DElement *_target;
const MDiagram *_diagram;
bool _check_needs_update;
bool _update_needed;
};
}
#endif // QMT_DUPDATEVISITOR_H

View File

@@ -0,0 +1,190 @@
/***************************************************************************
**
** 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 "dvoidvisitor.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/dpackage.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/dcomponent.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram/ditem.h"
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
namespace qmt {
DVoidVisitor::DVoidVisitor()
{
}
void DVoidVisitor::visitDElement(DElement *element)
{
Q_UNUSED(element);
}
void DVoidVisitor::visitDObject(DObject *object)
{
visitDElement(object);
}
void DVoidVisitor::visitDPackage(DPackage *package)
{
visitDObject(package);
}
void DVoidVisitor::visitDClass(DClass *klass)
{
visitDObject(klass);
}
void DVoidVisitor::visitDComponent(DComponent *component)
{
visitDObject(component);
}
void DVoidVisitor::visitDDiagram(DDiagram *diagram)
{
visitDObject(diagram);
}
void DVoidVisitor::visitDItem(DItem *item)
{
visitDObject(item);
}
void DVoidVisitor::visitDRelation(DRelation *relation)
{
visitDElement(relation);
}
void DVoidVisitor::visitDInheritance(DInheritance *inheritance)
{
visitDRelation(inheritance);
}
void DVoidVisitor::visitDDependency(DDependency *dependency)
{
visitDRelation(dependency);
}
void DVoidVisitor::visitDAssociation(DAssociation *association)
{
visitDRelation(association);
}
void DVoidVisitor::visitDAnnotation(DAnnotation *annotation)
{
visitDElement(annotation);
}
void DVoidVisitor::visitDBoundary(DBoundary *boundary)
{
visitDElement(boundary);
}
DConstVoidVisitor::DConstVoidVisitor()
{
}
void DConstVoidVisitor::visitDElement(const DElement *element)
{
Q_UNUSED(element);
}
void DConstVoidVisitor::visitDObject(const DObject *object)
{
visitDElement(object);
}
void DConstVoidVisitor::visitDPackage(const DPackage *package)
{
visitDObject(package);
}
void DConstVoidVisitor::visitDClass(const DClass *klass)
{
visitDObject(klass);
}
void DConstVoidVisitor::visitDComponent(const DComponent *component)
{
visitDObject(component);
}
void DConstVoidVisitor::visitDDiagram(const DDiagram *diagram)
{
visitDObject(diagram);
}
void DConstVoidVisitor::visitDItem(const DItem *item)
{
visitDObject(item);
}
void DConstVoidVisitor::visitDRelation(const DRelation *relation)
{
visitDElement(relation);
}
void DConstVoidVisitor::visitDInheritance(const DInheritance *inheritance)
{
visitDRelation(inheritance);
}
void DConstVoidVisitor::visitDDependency(const DDependency *dependency)
{
visitDRelation(dependency);
}
void DConstVoidVisitor::visitDAssociation(const DAssociation *association)
{
visitDRelation(association);
}
void DConstVoidVisitor::visitDAnnotation(const DAnnotation *annotation)
{
visitDElement(annotation);
}
void DConstVoidVisitor::visitDBoundary(const DBoundary *boundary)
{
visitDElement(boundary);
}
}

View File

@@ -0,0 +1,111 @@
/***************************************************************************
**
** 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 QMT_DVOIDVISITOR_H
#define QMT_DVOIDVISITOR_H
#include "qmt/diagram/dvisitor.h"
#include "qmt/diagram/dconstvisitor.h"
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class QMT_EXPORT DVoidVisitor :
public DVisitor
{
public:
DVoidVisitor();
void visitDElement(DElement *element);
void visitDObject(DObject *object);
void visitDPackage(DPackage *package);
void visitDClass(DClass *klass);
void visitDComponent(DComponent *component);
void visitDDiagram(DDiagram *diagram);
void visitDItem(DItem *item);
void visitDRelation(DRelation *relation);
void visitDInheritance(DInheritance *inheritance);
void visitDDependency(DDependency *dependency);
void visitDAssociation(DAssociation *association);
void visitDAnnotation(DAnnotation *annotation);
void visitDBoundary(DBoundary *boundary);
};
class QMT_EXPORT DConstVoidVisitor :
public DConstVisitor
{
public:
DConstVoidVisitor();
void visitDElement(const DElement *element);
void visitDObject(const DObject *object);
void visitDPackage(const DPackage *package);
void visitDClass(const DClass *klass);
void visitDComponent(const DComponent *component);
void visitDDiagram(const DDiagram *diagram);
void visitDItem(const DItem *item);
void visitDRelation(const DRelation *relation);
void visitDInheritance(const DInheritance *inheritance);
void visitDDependency(const DDependency *dependency);
void visitDAssociation(const DAssociation *association);
void visitDAnnotation(const DAnnotation *annotation);
void visitDBoundary(const DBoundary *boundary);
};
}
#endif // DVOIDVISITOR_H

View File

@@ -0,0 +1,65 @@
/***************************************************************************
**
** 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 QMT_ALIGNABLE_H
#define QMT_ALIGNABLE_H
#include <QString>
namespace qmt {
class IAlignable {
public:
enum AlignType {
ALIGN_LEFT,
ALIGN_RIGHT,
ALIGN_TOP,
ALIGN_BOTTOM,
ALIGN_HCENTER,
ALIGN_VCENTER,
ALIGN_WIDTH,
ALIGN_HEIGHT,
ALIGN_SIZE
};
public:
virtual ~IAlignable() { }
public:
virtual void align(AlignType align_type, const QString &identifier) = 0;
};
}
#endif // QMT_ALIGNABLE_H

View File

@@ -0,0 +1,49 @@
/***************************************************************************
**
** 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 QMT_EDITABLE_H
#define QMT_EDITABLE_H
namespace qmt {
class IEditable {
public:
~IEditable() { }
public:
virtual bool isEditable() const = 0;
virtual void edit() = 0;
};
}
#endif // QMT_EDITABLE_H

View File

@@ -0,0 +1,55 @@
/***************************************************************************
**
** 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 QMT_INTERSECTIONABLE_H
#define QMT_INTERSECTIONABLE_H
#include <QtGlobal>
QT_BEGIN_NAMESPACE
class QPointF;
class QLineF;
QT_END_NAMESPACE
namespace qmt {
class IIntersectionable {
public:
virtual ~IIntersectionable() { }
virtual bool intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line = 0) const = 0;
};
}
#endif // QMT_INTERSECTIONABLE_H

View File

@@ -0,0 +1,96 @@
/***************************************************************************
**
** 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 QMT_LATCHABLE_H
#define QMT_LATCHABLE_H
#include <QList>
namespace qmt {
class ILatchable {
public:
enum Action {
MOVE,
RESIZE_LEFT,
RESIZE_TOP,
RESIZE_RIGHT,
RESIZE_BOTTOM
};
enum LatchType {
NONE,
LEFT,
TOP,
RIGHT,
BOTTOM,
HCENTER,
VCENTER
};
struct Latch {
Latch()
: _latch_type(NONE),
_pos(0.0),
_other_pos1(0.0),
_other_pos2(0.0),
_identifier()
{
}
Latch(LatchType latch_type, qreal pos, qreal other_pos1, qreal other_pos2, const QString &identifier)
: _latch_type(latch_type),
_pos(pos),
_other_pos1(other_pos1),
_other_pos2(other_pos2),
_identifier(identifier)
{
}
LatchType _latch_type;
qreal _pos;
qreal _other_pos1, _other_pos2;
QString _identifier;
};
public:
virtual ~ILatchable() { }
virtual QList<Latch> getHorizontalLatches(Action action, bool grabbed_item) const = 0;
virtual QList<Latch> getVerticalLatches(Action action, bool grabbed_item) const = 0;
};
}
#endif // QMT_LATCHABLE_H

View File

@@ -0,0 +1,54 @@
/***************************************************************************
**
** 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 QMT_MOVEABLE_H
#define QMT_MOVEABLE_H
#include <QtGlobal>
QT_BEGIN_NAMESPACE
class QPointF;
QT_END_NAMESPACE
namespace qmt {
class IMoveable {
public:
virtual ~IMoveable() { }
virtual void moveDelta(const QPointF &delta) = 0;
virtual void alignItemPositionToRaster(double raster_width, double raster_height) = 0;
};
}
#endif // QMT_MOVEABLE_H

View File

@@ -0,0 +1,56 @@
/***************************************************************************
**
** 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 QMT_RELATIONABLE_H
#define QMT_RELATIONABLE_H
#include <QList>
QT_BEGIN_NAMESPACE
class QString;
class QGraphicsItem;
class QPointF;
QT_END_NAMESPACE
namespace qmt {
class IRelationable {
public:
virtual ~IRelationable() { }
virtual QPointF getRelationStartPos() const = 0;
virtual void relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points) = 0;
};
}
#endif // QMT_RELATIONABLE_H

View File

@@ -0,0 +1,70 @@
/***************************************************************************
**
** 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 QMT_RESIZABLE_H
#define QMT_RESIZABLE_H
#include <QtGlobal>
QT_BEGIN_NAMESPACE
class QPointF;
class QRectF;
class QSizeF;
QT_END_NAMESPACE
namespace qmt {
class IResizable {
public:
enum Side {
SIDE_NONE,
SIDE_LEFT_OR_TOP,
SIDE_RIGHT_OR_BOTTOM
};
public:
virtual ~IResizable() { }
virtual QPointF getPos() const = 0;
virtual QRectF getRect() const = 0;
virtual QSizeF getMinimumSize() const = 0;
virtual void setPosAndRect(const QPointF &original_pos, const QRectF &original_rect, const QPointF &top_left_delta, const QPointF &bottom_right_delta) = 0;
virtual void alignItemSizeToRaster(Side adjust_horizontal_side, Side adjust_vertical_side, double raster_width, double raster_height) = 0;
};
}
#endif // QMT_RESIZABLE_H

View File

@@ -0,0 +1,51 @@
/***************************************************************************
**
** 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 QMT_SELECTABLE_H
#define QMT_SELECTABLE_H
namespace qmt {
class ISelectable {
public:
virtual ~ISelectable() { }
virtual bool isSecondarySelected() const = 0;
virtual void setSecondarySelected(bool secondary_selected) = 0;
virtual bool isFocusSelected() const = 0;
virtual void setFocusSelected(bool focus_selected) = 0;
};
}
#endif // QMT_SELECTABLE_H

View File

@@ -0,0 +1,61 @@
/***************************************************************************
**
** 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 QMT_WINDABLE_H
#define QMT_WINDABLE_H
#include <QtGlobal>
QT_BEGIN_NAMESPACE
class QPointF;
QT_END_NAMESPACE
namespace qmt {
class IWindable {
public:
virtual ~IWindable() { }
virtual QPointF getHandlePos(int index) = 0;
virtual void insertHandle(int before_index, const QPointF &pos) = 0;
virtual void deleteHandle(int index) = 0;
virtual void setHandlePos(int index, const QPointF &pos) = 0;
virtual void alignHandleToRaster(int index, double raster_width, double raster_height) = 0;
};
}
#endif // QMT_WINDABLE_H

View File

@@ -0,0 +1,144 @@
/***************************************************************************
**
** 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 "diagramgraphicsscene.h"
#include "diagramscenemodel.h"
#include <QDebug>
namespace qmt {
DiagramGraphicsScene::DiagramGraphicsScene(DiagramSceneModel *diagram_scene_model, QObject *parent)
: QGraphicsScene(parent),
_diagram_scene_model(diagram_scene_model)
{
}
DiagramGraphicsScene::~DiagramGraphicsScene()
{
}
bool DiagramGraphicsScene::event(QEvent *event)
{
return QGraphicsScene::event(event);
}
bool DiagramGraphicsScene::eventFilter(QObject *watched, QEvent *event)
{
return QGraphicsScene::eventFilter(watched, event);
}
void DiagramGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QGraphicsScene::contextMenuEvent(event);
}
void DiagramGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dragEnterEvent(event);
}
void DiagramGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dragMoveEvent(event);
}
void DiagramGraphicsScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dragLeaveEvent(event);
}
void DiagramGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dropEvent(event);
}
void DiagramGraphicsScene::focusInEvent(QFocusEvent *event)
{
QGraphicsScene::focusInEvent(event);
}
void DiagramGraphicsScene::focusOutEvent(QFocusEvent *event)
{
QGraphicsScene::focusOutEvent(event);
}
void DiagramGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *event)
{
QGraphicsScene::helpEvent(event);
}
void DiagramGraphicsScene::keyPressEvent(QKeyEvent *event)
{
QGraphicsScene::keyPressEvent(event);
}
void DiagramGraphicsScene::keyReleaseEvent(QKeyEvent *event)
{
QGraphicsScene::keyReleaseEvent(event);
}
void DiagramGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
_diagram_scene_model->sceneActivated();
QGraphicsScene::mousePressEvent(event);
_diagram_scene_model->mousePressEvent(event);
}
void DiagramGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mouseMoveEvent(event);
_diagram_scene_model->mouseMoveEvent(event);
}
void DiagramGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mouseReleaseEvent(event);
_diagram_scene_model->mouseReleaseEvent(event);
}
void DiagramGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsScene::mouseDoubleClickEvent(event);
}
void DiagramGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *event)
{
QGraphicsScene::wheelEvent(event);
}
void DiagramGraphicsScene::inputMethodEvent(QInputMethodEvent *event)
{
QGraphicsScene::inputMethodEvent(event);
}
}

View File

@@ -0,0 +1,102 @@
/***************************************************************************
**
** 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 QMT_DIAGRAMGRAPHICSSCENE_H
#define QMT_DIAGRAMGRAPHICSSCENE_H
#include <QGraphicsScene>
#include "qmt/infrastructure/qmt_global.h"
namespace qmt {
class DiagramSceneModel;
class QMT_EXPORT DiagramGraphicsScene :
public QGraphicsScene
{
Q_OBJECT
public:
DiagramGraphicsScene(DiagramSceneModel *diagram_scene_model, QObject *parent = 0);
~DiagramGraphicsScene();
signals:
void sceneActivated();
protected:
bool event(QEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
void focusInEvent(QFocusEvent *event);
void focusOutEvent(QFocusEvent *event);
void helpEvent(QGraphicsSceneHelpEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void wheelEvent(QGraphicsSceneWheelEvent *event);
void inputMethodEvent(QInputMethodEvent *event);
private:
DiagramSceneModel *_diagram_scene_model;
};
}
#endif // QMT_DIAGRAMGRAPHICSSCENE_H

View File

@@ -0,0 +1,66 @@
/***************************************************************************
**
** 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 QMT_DIAGRAMSCENECONSTANTS_H
#define QMT_DIAGRAMSCENECONSTANTS_H
namespace qmt {
const int BOUNDARY_ITEMS_ZVALUE = -1000;
// all model objects have z-values from -500 to 500 depending on their depth in the model tree
const int RELATION_ITEMS_ZVALUE = 1000;
const int RELATION_ITEMS_ZVALUE_SELECTED = 1001;
const int ANNOTATION_ITEMS_ZVALUE = 1500;
const int RELATION_STARTER_ZVALUE = 2000;
const int LATCH_LINES_ZVALUE = 3000;
const int ALIGN_BUTTONS_ZVALUE = 3500;
const int PREVIEW_RELATION_ZVALUE = 4000;
const double RASTER_WIDTH = 5.0;
const double RASTER_HEIGHT = 5.0;
const double CUSTOM_ICON_MINIMUM_AUTO_WIDTH = 40.0; // must be n * 2 * RASTER_WIDTH
const double CUSTOM_ICON_MINIMUM_AUTO_HEIGHT = 40.0; // must be n * 2 * RASTER_HEIGHT
}
#endif // QMT_DIAGRAMSCENECONSTANTS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,282 @@
/***************************************************************************
**
** 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 QMT_DIAGRAMSCENEMODEL_H
#define QMT_DIAGRAMSCENEMODEL_H
#include <QObject>
#include "qmt/infrastructure/qmt_global.h"
#include <QList>
#include <QHash>
#include <QSet>
QT_BEGIN_NAMESPACE
class QGraphicsItem;
class QPointF;
class QGraphicsScene;
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE
namespace qmt {
class DiagramGraphicsScene;
class LatchController;
class Uid;
class DiagramController;
class DiagramSceneController;
class StereotypeController;
class StyleController;
class DSelection;
class MDiagram;
class DElement;
class DObject;
class QMT_EXPORT DiagramSceneModel :
public QObject
{
Q_OBJECT
class CreationVisitor;
class UpdateVisitor;
class OriginItem;
friend class UpdateVisitor;
friend class DiagramGraphicsScene;
public:
enum CollidingMode {
COLLIDING_INNER_ITEMS,
COLLIDING_ITEMS,
COLLIDING_OUTER_ITEMS
};
public:
DiagramSceneModel(QObject *parent = 0);
~DiagramSceneModel();
signals:
void diagramSceneActivated(const MDiagram *diagram);
void selectionChanged(const MDiagram *diagram);
public:
DiagramController *getDiagramController() const { return _diagram_controller; }
void setDiagramController(DiagramController *diagram_controller);
DiagramSceneController *getDiagramSceneController() const { return _diagram_scene_controller; }
void setDiagramSceneController(DiagramSceneController *diagram_scene_controller);
StyleController *getStyleController() const { return _style_controller; }
void setStyleController(StyleController *style_controller);
StereotypeController *getStereotypeController() const { return _stereotype_controller; }
void setStereotypeController(StereotypeController *stereotype_controller);
MDiagram *getDiagram() const { return _diagram; }
void setDiagram(MDiagram *diagram);
QGraphicsScene *getGraphicsScene() const;
public:
bool hasSelection() const;
bool hasMultiObjectsSelection() const;
DSelection getSelectedElements() const;
DElement *findTopmostElement(const QPointF &scene_pos) const;
public:
QList<QGraphicsItem *> getGraphicsItems() const { return _graphics_items; }
QGraphicsItem *getGraphicsItem(DElement *element) const;
QGraphicsItem *getGraphicsItem(const Uid &uid) const;
QGraphicsItem *getFocusItem() const { return _focus_item; }
bool isSelectedItem(QGraphicsItem *item) const;
QSet<QGraphicsItem *> getSelectedItems() const { return _selected_items; }
DElement *getElement(QGraphicsItem *item) const;
bool isElementEditable(const DElement *element) const;
public:
void selectAllElements();
void selectElement(DElement *element);
void editElement(DElement *element);
void copyToClipboard();
bool exportPng(const QString &file_name);
void exportPdf(const QString &file_name);
public:
void selectItem(QGraphicsItem *item, bool multi_select);
void moveSelectedItems(QGraphicsItem *grabbed_item, const QPointF &delta);
void alignSelectedItemsPositionOnRaster();
void onDoubleClickedItem(QGraphicsItem *item);
QList<QGraphicsItem *> collectCollidingObjectItems(const QGraphicsItem *item, CollidingMode colliding_mode) const;
private:
void sceneActivated();
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mousePressEventReparenting(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEventReparenting(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEventReparenting(QGraphicsSceneMouseEvent *event);
private slots:
void onBeginResetAllDiagrams();
void onEndResetAllDiagrams();
void onBeginResetDiagram(const MDiagram *diagram);
void onEndResetDiagram(const MDiagram *diagram);
void onBeginUpdateElement(int row, const MDiagram *diagram);
void onEndUpdateElement(int row, const MDiagram *diagram);
void onBeginInsertElement(int row, const MDiagram *diagram);
void onEndInsertElement(int row, const MDiagram *diagram);
void onBeginRemoveElement(int row, const MDiagram *diagram);
void onEndRemoveElement(int row, const MDiagram *diagram);
private slots:
void onSelectionChanged();
private:
void clearGraphicsScene();
void removeExtraSceneItems();
void addExtraSceneItems();
QGraphicsItem *createGraphicsItem(DElement *element);
void updateGraphicsItem(QGraphicsItem *item, DElement *element);
void deleteGraphicsItem(QGraphicsItem *item, DElement *element);
void updateFocusItem(const QSet<QGraphicsItem *> &selected_items);
void unsetFocusItem();
bool isInFrontOf(const QGraphicsItem *front_item, const QGraphicsItem *back_item);
private:
enum Busy {
NOT_BUSY,
RESET_DIAGRAM,
UPDATE_ELEMENT,
INSERT_ELEMENT,
REMOVE_ELEMENT
};
private:
DiagramController *_diagram_controller;
DiagramSceneController *_diagram_scene_controller;
StyleController *_style_controller;
StereotypeController *_stereotype_controller;
MDiagram *_diagram;
DiagramGraphicsScene *_graphics_scene;
LatchController *_latch_controller;
QList<QGraphicsItem *> _graphics_items;
QHash<const QGraphicsItem *, DElement *> _item_to_element_map;
QHash<const DElement *, QGraphicsItem *> _element_to_item_map;
QSet<QGraphicsItem *> _selected_items;
QSet<QGraphicsItem *> _secondary_selected_items;
Busy _busy;
OriginItem *_origin_item;
QGraphicsItem *_focus_item;
};
}
#endif // QMT_DIAGRAMSCENEMODEL_H

View File

@@ -0,0 +1,292 @@
/***************************************************************************
**
** 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 "diagramscenemodelitemvisitors.h"
#include "items/packageitem.h"
#include "items/classitem.h"
#include "items/componentitem.h"
#include "items/diagramitem.h"
#include "items/itemitem.h"
#include "items/relationitem.h"
#include "items/associationitem.h"
#include "items/annotationitem.h"
#include "items/boundaryitem.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram/dpackage.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/dcomponent.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram/ditem.h"
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/infrastructure/qmtassert.h"
namespace qmt {
DiagramSceneModel::CreationVisitor::CreationVisitor(DiagramSceneModel *diagram_scene_model)
: _diagram_scene_model(diagram_scene_model),
_graphics_item(0)
{
}
void DiagramSceneModel::CreationVisitor::visitDElement(DElement *element)
{
Q_UNUSED(element);
QMT_CHECK(false);
}
void DiagramSceneModel::CreationVisitor::visitDObject(DObject *object)
{
Q_UNUSED(object);
QMT_CHECK(false);
}
void DiagramSceneModel::CreationVisitor::visitDPackage(DPackage *package)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new PackageItem(package, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDClass(DClass *klass)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new ClassItem(klass, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDComponent(DComponent *component)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new ComponentItem(component, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDDiagram(DDiagram *diagram)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new DiagramItem(diagram, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDItem(DItem *item)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new ItemItem(item, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDRelation(DRelation *relation)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new RelationItem(relation, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDInheritance(DInheritance *inheritance)
{
visitDRelation(inheritance);
}
void DiagramSceneModel::CreationVisitor::visitDDependency(DDependency *dependency)
{
visitDRelation(dependency);
}
void DiagramSceneModel::CreationVisitor::visitDAssociation(DAssociation *association)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new AssociationItem(association, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDAnnotation(DAnnotation *annotation)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new AnnotationItem(annotation, _diagram_scene_model);
}
void DiagramSceneModel::CreationVisitor::visitDBoundary(DBoundary *boundary)
{
QMT_CHECK(!_graphics_item);
_graphics_item = new BoundaryItem(boundary, _diagram_scene_model);
}
DiagramSceneModel::UpdateVisitor::UpdateVisitor(QGraphicsItem *item, DiagramSceneModel *diagram_scene_model, DElement *related_element)
: _graphics_item(item),
_diagram_scene_model(diagram_scene_model),
_related_element(related_element)
{
}
void DiagramSceneModel::UpdateVisitor::visitDElement(DElement *element)
{
Q_UNUSED(element);
QMT_CHECK(false);
}
void DiagramSceneModel::UpdateVisitor::visitDObject(DObject *object)
{
if (_related_element == 0) {
// update all related relations
foreach (QGraphicsItem *item, _diagram_scene_model->_graphics_items) {
DElement *element = _diagram_scene_model->_item_to_element_map.value(item);
QMT_CHECK(element);
if (dynamic_cast<DRelation *>(element) != 0) {
UpdateVisitor visitor(item, _diagram_scene_model, object);
element->accept(&visitor);
}
}
}
}
void DiagramSceneModel::UpdateVisitor::visitDPackage(DPackage *package)
{
QMT_CHECK(_graphics_item);
if (_related_element == 0) {
PackageItem *package_item = qgraphicsitem_cast<PackageItem *>(_graphics_item);
QMT_CHECK(package_item);
QMT_CHECK(package_item->getObject() == package);
package_item->update();
}
visitDObject(package);
}
void DiagramSceneModel::UpdateVisitor::visitDClass(DClass *klass)
{
QMT_CHECK(_graphics_item);
if (_related_element == 0) {
ClassItem *class_item = qgraphicsitem_cast<ClassItem *>(_graphics_item);
QMT_CHECK(class_item);
QMT_CHECK(class_item->getObject() == klass);
class_item->update();
}
visitDObject(klass);
}
void DiagramSceneModel::UpdateVisitor::visitDComponent(DComponent *component)
{
QMT_CHECK(_graphics_item);
if (_related_element == 0) {
ComponentItem *component_item = qgraphicsitem_cast<ComponentItem *>(_graphics_item);
QMT_CHECK(component_item);
QMT_CHECK(component_item->getObject() == component);
component_item->update();
}
visitDObject(component);
}
void DiagramSceneModel::UpdateVisitor::visitDDiagram(DDiagram *diagram)
{
QMT_CHECK(_graphics_item);
if (_related_element == 0) {
DiagramItem *document_item = qgraphicsitem_cast<DiagramItem *>(_graphics_item);
QMT_CHECK(document_item);
QMT_CHECK(document_item->getObject() == diagram);
document_item->update();
}
visitDObject(diagram);
}
void DiagramSceneModel::UpdateVisitor::visitDItem(DItem *item)
{
QMT_CHECK(_graphics_item);
if (_related_element == 0) {
ItemItem *item_item = qgraphicsitem_cast<ItemItem *>(_graphics_item);
QMT_CHECK(item_item);
QMT_CHECK(item_item->getObject() == item);
item_item->update();
}
visitDObject(item);
}
void DiagramSceneModel::UpdateVisitor::visitDRelation(DRelation *relation)
{
QMT_CHECK(_graphics_item);
if (_related_element == 0 || _related_element->getUid() == relation->getEndA() || _related_element->getUid() == relation->getEndB()) {
RelationItem *relation_item = qgraphicsitem_cast<RelationItem *>(_graphics_item);
QMT_CHECK(relation_item);
QMT_CHECK(relation_item->getRelation() == relation);
relation_item->update();
}
}
void DiagramSceneModel::UpdateVisitor::visitDInheritance(DInheritance *inheritance)
{
visitDRelation(inheritance);
}
void DiagramSceneModel::UpdateVisitor::visitDDependency(DDependency *dependency)
{
visitDRelation(dependency);
}
void DiagramSceneModel::UpdateVisitor::visitDAssociation(DAssociation *association)
{
visitDRelation(association);
}
void DiagramSceneModel::UpdateVisitor::visitDAnnotation(DAnnotation *annotation)
{
Q_UNUSED(annotation); // avoid warning in release mode
QMT_CHECK(_graphics_item);
AnnotationItem *annotation_item = qgraphicsitem_cast<AnnotationItem *>(_graphics_item);
QMT_CHECK(annotation_item);
QMT_CHECK(annotation_item->getAnnotation() == annotation);
annotation_item->update();
}
void DiagramSceneModel::UpdateVisitor::visitDBoundary(DBoundary *boundary)
{
Q_UNUSED(boundary); // avoid warning in release mode
QMT_CHECK(_graphics_item);
BoundaryItem *boundary_item = qgraphicsitem_cast<BoundaryItem *>(_graphics_item);
QMT_CHECK(boundary_item);
QMT_CHECK(boundary_item->getBoundary() == boundary);
boundary_item->update();
}
}

View File

@@ -0,0 +1,132 @@
/***************************************************************************
**
** 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 QMT_DIAGRAMSCENEMODELITEMVISITORS_H
#define QMT_DIAGRAMSCENEMODELITEMVISITORS_H
#include "diagramscenemodel.h"
#include "qmt/diagram/dvisitor.h"
namespace qmt {
class QMT_EXPORT DiagramSceneModel::CreationVisitor :
public DVisitor
{
public:
CreationVisitor(DiagramSceneModel *diagram_scene_model);
public:
QGraphicsItem *getCreatedGraphicsItem() const { return _graphics_item; }
public:
void visitDElement(DElement *element);
void visitDObject(DObject *object);
void visitDPackage(DPackage *package);
void visitDClass(DClass *klass);
void visitDComponent(DComponent *component);
void visitDDiagram(DDiagram *diagram);
void visitDItem(DItem *item);
void visitDRelation(DRelation *relation);
void visitDInheritance(DInheritance *inheritance);
void visitDDependency(DDependency *dependency);
void visitDAssociation(DAssociation *association);
void visitDAnnotation(DAnnotation *annotation);
void visitDBoundary(DBoundary *boundary);
private:
DiagramSceneModel *_diagram_scene_model;
QGraphicsItem *_graphics_item;
};
class DiagramSceneModel::UpdateVisitor :
public DVisitor
{
public:
UpdateVisitor(QGraphicsItem *item, DiagramSceneModel *diagram_scene_model, DElement *related_element = 0);
public:
void visitDElement(DElement *element);
void visitDObject(DObject *object);
void visitDPackage(DPackage *package);
void visitDClass(DClass *klass);
void visitDComponent(DComponent *component);
void visitDDiagram(DDiagram *diagram);
void visitDItem(DItem *item);
void visitDRelation(DRelation *relation);
void visitDInheritance(DInheritance *inheritance);
void visitDDependency(DDependency *dependency);
void visitDAssociation(DAssociation *association);
void visitDAnnotation(DAnnotation *annotation);
void visitDBoundary(DBoundary *boundary);
private:
QGraphicsItem *_graphics_item;
DiagramSceneModel *_diagram_scene_model;
DElement *_related_element;
};
}
#endif // QMT_DIAGRAMSCENEMODELITEMVISITORS_H

View File

@@ -0,0 +1,395 @@
/***************************************************************************
**
** 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 "annotationitem.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/rectangularselectionitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/style.h"
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QTextDocument>
#include <QTextFrame>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneMouseEvent>
#include <QCoreApplication>
namespace qmt {
static const qreal MINIMUM_TEXT_WIDTH = 20.0;
static const qreal CONTENTS_BORDER_VERTICAL = 4.0;
static const qreal CONTENTS_BORDER_HORIZONTAL = 4.0;
class AnnotationItem::AnnotationTextItem :
public QGraphicsTextItem
{
public:
AnnotationTextItem(QGraphicsItem *parent)
: QGraphicsTextItem(parent)
{
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QMT_CHECK(option);
QStyleOptionGraphicsItem option2(*option);
option2.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
QGraphicsTextItem::paint(painter, &option2, widget);
}
};
AnnotationItem::AnnotationItem(DAnnotation *annotation, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: QGraphicsItem(parent),
_annotation(annotation),
_diagram_scene_model(diagram_scene_model),
_secondary_selected(false),
_focus_selected(false),
_selection_marker(0),
_no_text_item(0),
_text_item(0),
_on_update(false),
_on_changed(false)
{
setFlags(QGraphicsItem::ItemIsSelectable);
}
AnnotationItem::~AnnotationItem()
{
}
QRectF AnnotationItem::boundingRect() const
{
return childrenBoundingRect();
}
void AnnotationItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(painter);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void AnnotationItem::update()
{
QMT_CHECK(!_on_update);
_on_update = true;
prepareGeometryChange();
const Style *style = getAdaptedStyle();
// text
if (!_text_item) {
_text_item = new AnnotationTextItem(this);
_text_item->setTextInteractionFlags(Qt::TextEditorInteraction);
_text_item->installSceneEventFilter(this);
QObject::connect(_text_item->document(), &QTextDocument::contentsChanged, _text_item,
[=]() { this->onContentsChanged(); } );
}
_text_item->setFont(style->getNormalFont());
_text_item->setDefaultTextColor(style->getTextBrush().color());
if (!_on_changed) {
_text_item->setPlainText(getAnnotation()->getText());
}
// item shown if annotation has no text and is not selected
if (!_no_text_item) {
_no_text_item = new QGraphicsRectItem(this);
}
_no_text_item->setPen(QPen(QBrush(QColor(192, 192, 192)), 1, Qt::DashDotLine));
_no_text_item->setVisible(!isSelected() && _text_item->document()->isEmpty());
updateSelectionMarker();
updateGeometry();
setZValue(ANNOTATION_ITEMS_ZVALUE);
_on_update = false;
}
QPointF AnnotationItem::getPos() const
{
return _annotation->getPos();
}
QRectF AnnotationItem::getRect() const
{
return _annotation->getRect();
}
QSizeF AnnotationItem::getMinimumSize() const
{
return calcMinimumGeometry();
}
void AnnotationItem::setPosAndRect(const QPointF &original_pos, const QRectF &original_rect, const QPointF &top_left_delta, const QPointF &bottom_right_delta)
{
QPointF new_pos = original_pos;
QRectF new_rect = original_rect;
GeometryUtilities::adjustPosAndRect(&new_pos, &new_rect, top_left_delta, bottom_right_delta, QPointF(0.0, 0.0));
if (new_pos != _annotation->getPos() || new_rect != _annotation->getRect()) {
_diagram_scene_model->getDiagramController()->startUpdateElement(_annotation, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_GEOMETRY);
_annotation->setPos(new_pos);
if (new_rect.size() != _annotation->getRect().size()) {
_annotation->setAutoSize(false);
}
_annotation->setRect(new_rect);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_annotation, _diagram_scene_model->getDiagram(), false);
}
}
void AnnotationItem::alignItemSizeToRaster(Side adjust_horizontal_side, Side adjust_vertical_side, double raster_width, double raster_height)
{
Q_UNUSED(adjust_horizontal_side);
Q_UNUSED(adjust_vertical_side);
Q_UNUSED(raster_width);
Q_UNUSED(raster_height);
}
void AnnotationItem::moveDelta(const QPointF &delta)
{
_diagram_scene_model->getDiagramController()->startUpdateElement(_annotation, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_GEOMETRY);
_annotation->setPos(_annotation->getPos() + delta);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_annotation, _diagram_scene_model->getDiagram(), false);
}
void AnnotationItem::alignItemPositionToRaster(double raster_width, double raster_height)
{
QPointF pos = _annotation->getPos();
QRectF rect = _annotation->getRect();
QPointF top_left = pos + rect.topLeft();
double left_delta = qRound(top_left.x() / raster_width) * raster_width - top_left.x();
double top_delta = qRound(top_left.y() / raster_height) * raster_height - top_left.y();
QPointF top_left_delta(left_delta, top_delta);
setPosAndRect(pos, rect, top_left_delta, top_left_delta);
}
bool AnnotationItem::isSecondarySelected() const
{
return _secondary_selected;
}
void AnnotationItem::setSecondarySelected(bool secondary_selected)
{
if (_secondary_selected != secondary_selected) {
_secondary_selected = secondary_selected;
update();
}
}
bool AnnotationItem::isFocusSelected() const
{
return _focus_selected;
}
void AnnotationItem::setFocusSelected(bool focus_selected)
{
if (_focus_selected != focus_selected) {
_focus_selected = focus_selected;
update();
}
}
bool AnnotationItem::isEditable() const
{
return true;
}
void AnnotationItem::edit()
{
if (_text_item) {
_text_item->setFocus();
}
}
void AnnotationItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) {
_diagram_scene_model->selectItem(this, event->modifiers() & Qt::ControlModifier);
}
if (event->buttons() & Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, QPointF(0.0, 0.0));
}
}
void AnnotationItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, event->scenePos() - event->lastScenePos());
}
}
void AnnotationItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, event->scenePos() - event->lastScenePos());
if (event->scenePos() != event->buttonDownScenePos(Qt::LeftButton)) {
_diagram_scene_model->alignSelectedItemsPositionOnRaster();
}
}
}
void AnnotationItem::updateSelectionMarker()
{
if (isSelected() || _secondary_selected) {
if (!_selection_marker) {
_selection_marker = new RectangularSelectionItem(this, this);
_selection_marker->setShowBorder(true);
_selection_marker->setFreedom(RectangularSelectionItem::FREEDOM_HORIZONTAL_ONLY);
}
_selection_marker->setSecondarySelected(isSelected() ? false : _secondary_selected);
} else if (_selection_marker) {
if (_selection_marker->scene()) {
_selection_marker->scene()->removeItem(_selection_marker);
}
delete _selection_marker;
_selection_marker = 0;
}
}
void AnnotationItem::updateSelectionMarkerGeometry(const QRectF &annotation_rect)
{
if (_selection_marker) {
_selection_marker->setRect(annotation_rect);
}
}
const Style *AnnotationItem::getAdaptedStyle()
{
return _diagram_scene_model->getStyleController()->adaptAnnotationStyle(_annotation);
}
bool AnnotationItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
if (watched == _text_item) {
if (event->type() == QEvent::FocusIn) {
scene()->clearSelection();
setSelected(true);
}
}
return false;
}
void AnnotationItem::onContentsChanged()
{
QMT_CHECK(!_on_changed);
_on_changed = true;
if (!_on_update) {
QString plain_text = _text_item->toPlainText();
if (_annotation->getText() != plain_text) {
_diagram_scene_model->getDiagramController()->startUpdateElement(_annotation, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_MINOR);
_annotation->setText(plain_text);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_annotation, _diagram_scene_model->getDiagram(), false);
}
}
_on_changed = false;
}
QSizeF AnnotationItem::calcMinimumGeometry() const
{
qreal width = MINIMUM_TEXT_WIDTH + 2 * CONTENTS_BORDER_HORIZONTAL;
qreal height = 0.0; // irrelevant; cannot be modified by user and will always be overwritten
if (getAnnotation()->hasAutoSize()) {
if (_text_item) {
_text_item->setTextWidth(-1);
QSizeF text_size = _text_item->document()->size();
width = text_size.width() + 2 * CONTENTS_BORDER_HORIZONTAL;
}
}
return QSizeF(width, height);
}
void AnnotationItem::updateGeometry()
{
prepareGeometryChange();
QSizeF geometry = calcMinimumGeometry();
qreal width = geometry.width();
qreal height = geometry.height();
if (getAnnotation()->hasAutoSize()) {
if (_text_item) {
_text_item->setTextWidth(-1);
QSizeF text_size = _text_item->document()->size();
width = text_size.width() + 2 * CONTENTS_BORDER_HORIZONTAL;
height = text_size.height() + 2 * CONTENTS_BORDER_VERTICAL;
}
} else {
QRectF rect = getAnnotation()->getRect();
width = rect.width();
if (_text_item) {
_text_item->setTextWidth(width - 2 * CONTENTS_BORDER_HORIZONTAL);
height = _text_item->document()->size().height() + 2 * CONTENTS_BORDER_VERTICAL;
}
}
// update sizes and positions
double left = 0.0;
double top = 0.0;
setPos(getAnnotation()->getPos());
QRectF rect(left, top, width, height);
// the object is updated without calling DiagramController intentionally.
// attribute rect is not a real attribute stored on DObject but
// a backup for the graphics item used for manual resized and persistency.
getAnnotation()->setRect(rect);
if (_no_text_item) {
_no_text_item->setRect(rect);
}
if (_text_item) {
_text_item->setPos(left + CONTENTS_BORDER_HORIZONTAL, top + CONTENTS_BORDER_VERTICAL);
}
updateSelectionMarkerGeometry(rect);
}
}

View File

@@ -0,0 +1,166 @@
/***************************************************************************
**
** 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 QMT_ANNOTATIONITEM_H
#define QMT_ANNOTATIONITEM_H
#include <QGraphicsItem>
#include "qmt/diagram_scene/capabilities/resizable.h"
#include "qmt/diagram_scene/capabilities/moveable.h"
#include "qmt/diagram_scene/capabilities/selectable.h"
#include "qmt/diagram_scene/capabilities/editable.h"
namespace qmt {
class DAnnotation;
class DiagramSceneModel;
class RectangularSelectionItem;
class Style;
class AnnotationItem :
public QGraphicsItem,
public IResizable,
public IMoveable,
public ISelectable,
public IEditable
{
class AnnotationTextItem;
public:
AnnotationItem(DAnnotation *annotation, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~AnnotationItem();
public:
DAnnotation *getAnnotation() const { return _annotation; }
DiagramSceneModel *getDiagramSceneModel() const { return _diagram_scene_model; }
public:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
public:
virtual void update();
public:
QPointF getPos() const;
QRectF getRect() const;
QSizeF getMinimumSize() const;
void setPosAndRect(const QPointF &original_pos, const QRectF &original_rect, const QPointF &top_left_delta, const QPointF &bottom_right_delta);
void alignItemSizeToRaster(Side adjust_horizontal_side, Side adjust_vertical_side, double raster_width, double raster_height);
public:
void moveDelta(const QPointF &delta);
void alignItemPositionToRaster(double raster_width, double raster_height);
public:
bool isSecondarySelected() const;
void setSecondarySelected(bool secondary_selected);
bool isFocusSelected() const;
void setFocusSelected(bool focus_selected);
public:
bool isEditable() const;
void edit();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
protected:
void updateSelectionMarker();
void updateSelectionMarkerGeometry(const QRectF &annotation_rect);
const Style *getAdaptedStyle();
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private slots:
void onContentsChanged();
private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
private:
DAnnotation *_annotation;
DiagramSceneModel *_diagram_scene_model;
bool _secondary_selected;
bool _focus_selected;
RectangularSelectionItem *_selection_marker;
QGraphicsRectItem *_no_text_item;
AnnotationTextItem *_text_item;
bool _on_update;
bool _on_changed;
};
}
#endif // QMT_ANNOTATIONITEM_H

View File

@@ -0,0 +1,181 @@
/***************************************************************************
**
** 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 "associationitem.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram_scene/capabilities/intersectionable.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/arrowitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/style/style.h"
#include <QGraphicsScene>
#include <QFont>
#include <QPen>
#include <QBrush>
#include <QVector2D>
#include <QPair>
#include <qdebug.h>
namespace qmt {
AssociationItem::AssociationItem(DAssociation *association, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: RelationItem(association, diagram_scene_model, parent),
_association(association),
_end_a_name(0),
_end_a_cardinality(0),
_end_b_name(0),
_end_b_cardinality(0)
{
}
AssociationItem::~AssociationItem()
{
}
void AssociationItem::update(const Style *style)
{
RelationItem::update(style);
updateEndLabels(_association->getA(), _association->getB(), &_end_a_name, &_end_a_cardinality, style);
updateEndLabels(_association->getB(), _association->getA(), &_end_b_name, &_end_b_cardinality, style);
QMT_CHECK(_arrow);
QGraphicsItem *end_a_item = _diagram_scene_model->getGraphicsItem(_association->getEndA());
QMT_CHECK(end_a_item);
placeEndLabels(_arrow->getFirstLineSegment(), _end_a_name, _end_a_cardinality, end_a_item, _arrow->getStartHeadLength());
QGraphicsItem *end_b_item = _diagram_scene_model->getGraphicsItem(_association->getEndB());
QMT_CHECK(end_b_item);
placeEndLabels(_arrow->getLastLineSegment(), _end_b_name, _end_b_cardinality, end_b_item, _arrow->getEndHeadLength());
}
void AssociationItem::updateEndLabels(const DAssociationEnd &end, const DAssociationEnd &other_end, QGraphicsSimpleTextItem **end_name, QGraphicsSimpleTextItem **end_cardinality, const Style *style)
{
Q_UNUSED(end);
if (!other_end.getName().isEmpty()) {
if (!*end_name) {
*end_name = new QGraphicsSimpleTextItem(this);
}
(*end_name)->setFont(style->getSmallFont());
(*end_name)->setBrush(style->getTextBrush());
(*end_name)->setText(other_end.getName());
} else if (*end_name) {
(*end_name)->scene()->removeItem(*end_name);
delete *end_name;
*end_name = 0;
}
if (!other_end.getCardinality().isEmpty()) {
if (!*end_cardinality) {
*end_cardinality = new QGraphicsSimpleTextItem(this);
}
(*end_cardinality)->setFont(style->getSmallFont());
(*end_cardinality)->setBrush(style->getTextBrush());
(*end_cardinality)->setText(other_end.getCardinality());
} else if (*end_cardinality) {
(*end_cardinality)->scene()->removeItem(*end_cardinality);
delete *end_cardinality;
*end_cardinality = 0;
}
}
void AssociationItem::placeEndLabels(const QLineF &line_segment, QGraphicsItem *end_name, QGraphicsItem *end_cardinality, QGraphicsItem *end_item, double head_length)
{
const double HEAD_OFFSET = head_length + 6.0;
const double SIDE_OFFSET = 4.0;
QPointF head_offset = QPointF(HEAD_OFFSET, 0);
QPointF side_offset = QPointF(0.0, SIDE_OFFSET);
double angle = GeometryUtilities::calcAngle(line_segment);
if (angle >= -5 && angle <= 5) {
if (end_name) {
end_name->setPos(line_segment.p1() + head_offset + side_offset);
}
if (end_cardinality) {
end_cardinality->setPos(line_segment.p1() + head_offset - side_offset - end_cardinality->boundingRect().bottomLeft());
}
} else if (angle <= -175 || angle >= 175) {
if (end_name) {
end_name->setPos(line_segment.p1() - head_offset + side_offset - end_name->boundingRect().topRight());
}
if (end_cardinality) {
end_cardinality->setPos(line_segment.p1() - head_offset - side_offset - end_cardinality->boundingRect().bottomRight());
}
} else {
QRectF rect;
if (end_cardinality) {
rect = end_cardinality->boundingRect();
}
if (end_name) {
rect = rect.united(end_name->boundingRect().translated(rect.bottomLeft()));
}
QPointF rect_placement;
GeometryUtilities::Side aligned_side = GeometryUtilities::SIDE_UNSPECIFIED;
if (IIntersectionable *object_item = dynamic_cast<IIntersectionable *>(end_item)) {
QPointF intersection_point;
QLineF intersection_line;
if (object_item->intersectShapeWithLine(GeometryUtilities::stretch(line_segment.translated(pos()), 2.0, 0.0), &intersection_point, &intersection_line)) {
if (!GeometryUtilities::placeRectAtLine(rect, line_segment, HEAD_OFFSET, SIDE_OFFSET, intersection_line, &rect_placement, &aligned_side)) {
rect_placement = intersection_point;
}
} else {
rect_placement = line_segment.p1();
}
} else {
rect_placement = end_item->pos();
}
if (end_cardinality) {
if (aligned_side == GeometryUtilities::SIDE_RIGHT) {
end_cardinality->setPos(rect_placement + QPointF(rect.width() - end_cardinality->boundingRect().width(), 0.0));
} else {
end_cardinality->setPos(rect_placement);
}
rect_placement += end_cardinality->boundingRect().bottomLeft();
}
if (end_name) {
if (aligned_side == GeometryUtilities::SIDE_RIGHT) {
end_name->setPos(rect_placement + QPointF(rect.width() - end_name->boundingRect().width(), 0.0));
} else {
end_name->setPos(rect_placement);
}
}
}
}
}

View File

@@ -0,0 +1,82 @@
/***************************************************************************
**
** 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 QMT_GRAPHICSASSOCIATIONITEM_H
#define QMT_GRAPHICSASSOCIATIONITEM_H
#include "relationitem.h"
QT_BEGIN_NAMESPACE
class QGraphicsSimpleTextItem;
QT_END_NAMESPACE
namespace qmt {
class DAssociation;
class DAssociationEnd;
class AssociationItem :
public RelationItem
{
public:
AssociationItem(DAssociation *association, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~AssociationItem();
protected:
virtual void update(const Style *style);
private:
void updateEndLabels(const DAssociationEnd &end, const DAssociationEnd &other_end, QGraphicsSimpleTextItem **end_name, QGraphicsSimpleTextItem **end_cardinality, const Style *style);
void placeEndLabels(const QLineF &line_segment, QGraphicsItem *end_name, QGraphicsItem *end_cardinality, QGraphicsItem *end_item, double head_length);
private:
DAssociation *_association;
QGraphicsSimpleTextItem *_end_a_name;
QGraphicsSimpleTextItem *_end_a_cardinality;
QGraphicsSimpleTextItem *_end_b_name;
QGraphicsSimpleTextItem *_end_b_cardinality;
};
}
#endif // QMT_GRAPHICSASSOCIATIONITEM_H

View File

@@ -0,0 +1,456 @@
/***************************************************************************
**
** 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 "boundaryitem.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/diagram_scene/capabilities/moveable.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/rectangularselectionitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/style.h"
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QTextDocument>
#include <QTextFrame>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneMouseEvent>
#include <QCoreApplication>
namespace qmt {
static const qreal MINIMUM_INNER_WIDTH = 22.0;
static const qreal MINIMUM_INNER_HEIGHT = 22.0;
static const qreal CONTENTS_BORDER_VERTICAL = 4.0;
static const qreal CONTENTS_BORDER_HORIZONTAL = 4.0;
class BoundaryItem::BoundaryTextItem :
public QGraphicsTextItem
{
public:
BoundaryTextItem(QGraphicsItem *parent)
: QGraphicsTextItem(parent)
{
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QMT_CHECK(option);
QStyleOptionGraphicsItem option2(*option);
option2.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
QGraphicsTextItem::paint(painter, &option2, widget);
}
};
BoundaryItem::BoundaryItem(DBoundary *boundary, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: QGraphicsItem(parent),
_boundary(boundary),
_diagram_scene_model(diagram_scene_model),
_secondary_selected(false),
_focus_selected(false),
_selection_marker(0),
_border_item(0),
_no_text_item(0),
_text_item(0),
_on_update(false),
_on_changed(false)
{
setFlags(QGraphicsItem::ItemIsSelectable);
}
BoundaryItem::~BoundaryItem()
{
}
QRectF BoundaryItem::boundingRect() const
{
return childrenBoundingRect();
}
void BoundaryItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(painter);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void BoundaryItem::update()
{
QMT_CHECK(!_on_update);
_on_update = true;
prepareGeometryChange();
const Style *style = getAdaptedStyle();
// text
if (!_text_item) {
_text_item = new BoundaryTextItem(this);
_text_item->setTextInteractionFlags(Qt::TextEditorInteraction);
_text_item->installSceneEventFilter(this);
QObject::connect(_text_item->document(), &QTextDocument::contentsChanged, _text_item,
[=]() { this->onContentsChanged(); } );
}
_text_item->setFont(style->getNormalFont());
_text_item->setDefaultTextColor(style->getTextBrush().color());
if (!_on_changed) {
_text_item->setTextWidth(-1);
_text_item->setPlainText(_boundary->getText());
}
// item shown if annotation has no text and is not selected
if (_text_item->document()->isEmpty() && isSelected()) {
if (!_no_text_item) {
_no_text_item = new QGraphicsRectItem(this);
}
_no_text_item->setPen(QPen(QBrush(QColor(192, 192, 192)), 1, Qt::DashDotLine));
} else if (_no_text_item) {
_no_text_item->scene()->removeItem(_no_text_item);
delete _no_text_item;
_no_text_item = 0;
}
// item shown if annotation has no text and is not selected
if (!_border_item) {
_border_item = new QGraphicsRectItem(this);
}
_border_item->setPen(QPen(QBrush(Qt::black), 1, Qt::DashLine));
updateSelectionMarker();
updateGeometry();
setZValue(BOUNDARY_ITEMS_ZVALUE);
_on_update = false;
}
QPointF BoundaryItem::getPos() const
{
return _boundary->getPos();
}
QRectF BoundaryItem::getRect() const
{
return _boundary->getRect();
}
QSizeF BoundaryItem::getMinimumSize() const
{
return calcMinimumGeometry();
}
void BoundaryItem::setPosAndRect(const QPointF &original_pos, const QRectF &original_rect, const QPointF &top_left_delta, const QPointF &bottom_right_delta)
{
QPointF new_pos = original_pos;
QRectF new_rect = original_rect;
GeometryUtilities::adjustPosAndRect(&new_pos, &new_rect, top_left_delta, bottom_right_delta, QPointF(0.5, 0.5));
if (new_pos != _boundary->getPos() || new_rect != _boundary->getRect()) {
_diagram_scene_model->getDiagramController()->startUpdateElement(_boundary, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_GEOMETRY);
_boundary->setPos(new_pos);
_boundary->setRect(new_rect);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_boundary, _diagram_scene_model->getDiagram(), false);
}
}
void BoundaryItem::alignItemSizeToRaster(IResizable::Side adjust_horizontal_side, IResizable::Side adjust_vertical_side, double raster_width, double raster_height)
{
QPointF pos = _boundary->getPos();
QRectF rect = _boundary->getRect();
double horiz_delta = rect.width() - qRound(rect.width() / raster_width) * raster_width;
double vert_delta = rect.height() - qRound(rect.height() / raster_height) * raster_height;
// make sure the new size is at least the minimum size
QSizeF minimum_size = getMinimumSize();
while (rect.width() + horiz_delta < minimum_size.width()) {
horiz_delta += raster_width;
}
while (rect.height() + vert_delta < minimum_size.height()) {
vert_delta += raster_height;
}
double left_delta = 0.0;
double right_delta = 0.0;
double top_delta = 0.0;
double bottom_delta = 0.0;
switch (adjust_horizontal_side) {
case IResizable::SIDE_NONE:
break;
case IResizable::SIDE_LEFT_OR_TOP:
left_delta = horiz_delta;
break;
case IResizable::SIDE_RIGHT_OR_BOTTOM:
right_delta = -horiz_delta;
break;
}
switch (adjust_vertical_side) {
case IResizable::SIDE_NONE:
break;
case IResizable::SIDE_LEFT_OR_TOP:
top_delta = vert_delta;
break;
case IResizable::SIDE_RIGHT_OR_BOTTOM:
bottom_delta = -vert_delta;
break;
}
QPointF top_left_delta(left_delta, top_delta);
QPointF bottom_right_delta(right_delta, bottom_delta);
setPosAndRect(pos, rect, top_left_delta, bottom_right_delta);
}
void BoundaryItem::moveDelta(const QPointF &delta)
{
_diagram_scene_model->getDiagramController()->startUpdateElement(_boundary, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_GEOMETRY);
_boundary->setPos(_boundary->getPos() + delta);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_boundary, _diagram_scene_model->getDiagram(), false);
}
void BoundaryItem::alignItemPositionToRaster(double raster_width, double raster_height)
{
QPointF pos = _boundary->getPos();
QRectF rect = _boundary->getRect();
QPointF top_left = pos + rect.topLeft();
double left_delta = qRound(top_left.x() / raster_width) * raster_width - top_left.x();
double top_delta = qRound(top_left.y() / raster_height) * raster_height - top_left.y();
QPointF top_left_delta(left_delta, top_delta);
setPosAndRect(pos, rect, top_left_delta, top_left_delta);
}
bool BoundaryItem::isSecondarySelected() const
{
return _secondary_selected;
}
void BoundaryItem::setSecondarySelected(bool secondary_selected)
{
if (_secondary_selected != secondary_selected) {
_secondary_selected = secondary_selected;
update();
}
}
bool BoundaryItem::isFocusSelected() const
{
return _focus_selected;
}
void BoundaryItem::setFocusSelected(bool focus_selected)
{
if (_focus_selected != focus_selected) {
_focus_selected = focus_selected;
update();
}
}
bool BoundaryItem::isEditable() const
{
return true;
}
void BoundaryItem::edit()
{
if (_text_item) {
_text_item->setFocus();
}
}
void BoundaryItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) {
_diagram_scene_model->selectItem(this, event->modifiers() & Qt::ControlModifier);
}
if (event->buttons() & Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, QPointF(0.0, 0.0));
}
}
void BoundaryItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, event->scenePos() - event->lastScenePos());
}
}
void BoundaryItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, event->scenePos() - event->lastScenePos());
if (event->scenePos() != event->buttonDownScenePos(Qt::LeftButton)) {
_diagram_scene_model->alignSelectedItemsPositionOnRaster();
}
}
}
void BoundaryItem::updateSelectionMarker()
{
if (isSelected() || _secondary_selected) {
if (!_selection_marker) {
_selection_marker = new RectangularSelectionItem(this, this);
}
_selection_marker->setSecondarySelected(isSelected() ? false : _secondary_selected);
} else if (_selection_marker) {
if (_selection_marker->scene()) {
_selection_marker->scene()->removeItem(_selection_marker);
}
delete _selection_marker;
_selection_marker = 0;
}
}
void BoundaryItem::updateSelectionMarkerGeometry(const QRectF &boundary_rect)
{
if (_selection_marker) {
_selection_marker->setRect(boundary_rect);
}
}
const Style *BoundaryItem::getAdaptedStyle()
{
return _diagram_scene_model->getStyleController()->adaptBoundaryStyle(_boundary);
}
bool BoundaryItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
if (watched == _text_item) {
if (event->type() == QEvent::FocusIn) {
scene()->clearSelection();
setSelected(true);
}
}
return false;
}
void BoundaryItem::onContentsChanged()
{
QMT_CHECK(!_on_changed);
_on_changed = true;
if (!_on_update) {
QString plain_text = _text_item->toPlainText();
if (_boundary->getText() != plain_text) {
_diagram_scene_model->getDiagramController()->startUpdateElement(_boundary, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_MINOR);
_boundary->setText(plain_text);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_boundary, _diagram_scene_model->getDiagram(), false);
}
}
_on_changed = false;
}
QSizeF BoundaryItem::calcMinimumGeometry() const
{
qreal width = MINIMUM_INNER_WIDTH + 2 * CONTENTS_BORDER_HORIZONTAL;
qreal height = MINIMUM_INNER_HEIGHT + 2 * CONTENTS_BORDER_VERTICAL;
if (_text_item) {
_text_item->setTextWidth(-1);
QSizeF text_size = _text_item->document()->size();
qreal text_width = text_size.width() + 2 * CONTENTS_BORDER_HORIZONTAL;
if (text_width > width) {
width = text_width;
}
qreal text_height = text_size.height() + 2 * CONTENTS_BORDER_VERTICAL;
if (text_height > height) {
height = text_height;
}
}
return GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT);
}
void BoundaryItem::updateGeometry()
{
prepareGeometryChange();
QSizeF geometry = calcMinimumGeometry();
qreal width = geometry.width();
qreal height = geometry.height();
qreal text_width = 0.0;
qreal text_height = 0.0;
if (_text_item) {
_text_item->setTextWidth(-1);
QSizeF text_size = _text_item->document()->size();
text_width = text_size.width();
text_height = text_size.height();
}
QRectF boundary_rect = _boundary->getRect();
if (boundary_rect.width() > width) {
width = boundary_rect.width();
}
if (boundary_rect.height() > height) {
height = boundary_rect.height();
}
// update sizes and positions
double left = -width / 2.0;
double top = -height / 2.0;
setPos(_boundary->getPos());
QRectF rect(left, top, width, height);
// the object is updated without calling DiagramController intentionally.
// attribute rect is not a real attribute stored on DObject but
// a backup for the graphics item used for manual resized and persistency.
_boundary->setRect(rect);
if (_border_item) {
_border_item->setRect(rect);
}
if (_no_text_item) {
_no_text_item->setRect(QRectF(-text_width / 2, top + CONTENTS_BORDER_VERTICAL, text_width, text_height));
}
if (_text_item) {
_text_item->setPos(-text_width / 2.0, top + CONTENTS_BORDER_VERTICAL);
}
updateSelectionMarkerGeometry(rect);
}
}

View File

@@ -0,0 +1,167 @@
/***************************************************************************
**
** 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 QMT_BOUNDARYITEM_H
#define QMT_BOUNDARYITEM_H
#include <QGraphicsItem>
#include "qmt/diagram_scene/capabilities/resizable.h"
#include "qmt/diagram_scene/capabilities/moveable.h"
#include "qmt/diagram_scene/capabilities/selectable.h"
#include "qmt/diagram_scene/capabilities/editable.h"
namespace qmt {
class DBoundary;
class DiagramSceneModel;
class RectangularSelectionItem;
class Style;
class BoundaryItem :
public QGraphicsItem,
public IResizable,
public IMoveable,
public ISelectable,
public IEditable
{
class BoundaryTextItem;
public:
BoundaryItem(DBoundary *boundary, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~BoundaryItem();
public:
DBoundary *getBoundary() const { return _boundary; }
DiagramSceneModel *getDiagramSceneModel() const { return _diagram_scene_model; }
public:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
public:
virtual void update();
public:
QPointF getPos() const;
QRectF getRect() const;
QSizeF getMinimumSize() const;
void setPosAndRect(const QPointF &original_pos, const QRectF &original_rect, const QPointF &top_left_delta, const QPointF &bottom_right_delta);
void alignItemSizeToRaster(Side adjust_horizontal_side, Side adjust_vertical_side, double raster_width, double raster_height);
public:
void moveDelta(const QPointF &delta);
void alignItemPositionToRaster(double raster_width, double raster_height);
public:
bool isSecondarySelected() const;
void setSecondarySelected(bool secondary_selected);
bool isFocusSelected() const;
void setFocusSelected(bool focus_selected);
public:
bool isEditable() const;
void edit();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
protected:
void updateSelectionMarker();
void updateSelectionMarkerGeometry(const QRectF &boundary_rect);
const Style *getAdaptedStyle();
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private slots:
void onContentsChanged();
private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
private:
DBoundary *_boundary;
DiagramSceneModel *_diagram_scene_model;
bool _secondary_selected;
bool _focus_selected;
RectangularSelectionItem *_selection_marker;
QGraphicsRectItem *_border_item;
QGraphicsRectItem *_no_text_item;
BoundaryTextItem *_text_item;
bool _on_update;
bool _on_changed;
};
}
#endif // QMT_BOUNDARYITEM_H

View File

@@ -0,0 +1,742 @@
/***************************************************************************
**
** 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 "classitem.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/contextlabelitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/diagram_scene/parts/templateparameterbox.h"
#include "qmt/infrastructure/contextmenuaction.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/model/mclassmember.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/stereotype/stereotypeicon.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/style.h"
#include "qmt/tasks/diagramscenecontroller.h"
#include "qmt/tasks/ielementtasks.h"
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsSimpleTextItem>
#include <QGraphicsLineItem>
#include <QBrush>
#include <QPen>
#include <QFont>
#include <QMenu>
#include <algorithm>
namespace qmt {
static const qreal MINIMUM_AUTO_WIDTH = 80.0;
static const qreal MINIMUM_AUTO_HEIGHT = 60.0;
static const qreal BODY_VERT_BORDER = 4.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
ClassItem::ClassItem(DClass *klass, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: ObjectItem(klass, diagram_scene_model, parent),
_custom_icon(0),
_shape(0),
_namespace(0),
_class_name(0),
_context_label(0),
_attributes_separator(0),
_attributes(0),
_methods_separator(0),
_methods(0),
_template_parameter_box(0),
_relation_starter(0)
{
}
ClassItem::~ClassItem()
{
}
void ClassItem::update()
{
prepareGeometryChange();
updateStereotypeIconDisplay();
DClass *diagram_class = dynamic_cast<DClass *>(getObject());
QMT_CHECK(diagram_class);
const Style *style = getAdaptedStyle(getStereotypeIconId());
if (diagram_class->getShowAllMembers()) {
updateMembers(style);
} else {
_attributes_text.clear();
_methods_text.clear();
}
// custom icon
if (getStereotypeIconDisplay() == StereotypeIcon::DISPLAY_ICON) {
if (!_custom_icon) {
_custom_icon = new CustomIconItem(getDiagramSceneModel(), this);
}
_custom_icon->setStereotypeIconId(getStereotypeIconId());
_custom_icon->setBaseSize(getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT));
_custom_icon->setBrush(style->getFillBrush());
_custom_icon->setPen(style->getOuterLinePen());
_custom_icon->setZValue(SHAPE_ZVALUE);
} else if (_custom_icon) {
_custom_icon->scene()->removeItem(_custom_icon);
delete _custom_icon;
_custom_icon = 0;
}
// shape
if (!_custom_icon) {
if (!_shape) {
_shape = new QGraphicsRectItem(this);
}
_shape->setBrush(style->getFillBrush());
_shape->setPen(style->getOuterLinePen());
_shape->setZValue(SHAPE_ZVALUE);
} else if (_shape){
_shape->scene()->removeItem(_shape);
delete _shape;
_shape = 0;
}
// stereotypes
updateStereotypes(getStereotypeIconId(), getStereotypeIconDisplay(), style);
// namespace
if (!diagram_class->getNamespace().isEmpty()) {
if (!_namespace) {
_namespace = new QGraphicsSimpleTextItem(this);
}
_namespace->setFont(style->getSmallFont());
_namespace->setBrush(style->getTextBrush());
_namespace->setText(diagram_class->getNamespace());
} else if (_namespace) {
_namespace->scene()->removeItem(_namespace);
delete _namespace;
_namespace = 0;
}
DClass::TemplateDisplay template_display = diagram_class->getTemplateDisplay();
if (template_display == DClass::TEMPLATE_SMART) {
if (_custom_icon) {
template_display = DClass::TEMPLATE_NAME;
} else {
template_display = DClass::TEMPLATE_BOX;
}
}
// class name
if (!_class_name) {
_class_name = new QGraphicsSimpleTextItem(this);
}
_class_name->setFont(style->getHeaderFont());
_class_name->setBrush(style->getTextBrush());
if (template_display == DClass::TEMPLATE_NAME && !diagram_class->getTemplateParameters().isEmpty()) {
QString name = getObject()->getName();
name += QLatin1Char('<');
bool first = true;
foreach (const QString p, diagram_class->getTemplateParameters()) {
if (!first) {
name += QLatin1Char(',');
}
name += p;
first = false;
}
name += QLatin1Char('>');
_class_name->setText(name);
} else {
_class_name->setText(getObject()->getName());
}
// context
if (showContext()) {
if (!_context_label) {
_context_label = new ContextLabelItem(this);
}
_context_label->setFont(style->getSmallFont());
_context_label->setBrush(style->getTextBrush());
_context_label->setContext(getObject()->getContext());
} else if (_context_label) {
_context_label->scene()->removeItem(_context_label);
delete _context_label;
_context_label = 0;
}
// attributes separator
if (_shape || !_attributes_text.isEmpty() || !_methods_text.isEmpty()) {
if (!_attributes_separator) {
_attributes_separator = new QGraphicsLineItem(this);
}
_attributes_separator->setPen(style->getInnerLinePen());
_attributes_separator->setZValue(SHAPE_DETAILS_ZVALUE);
} else if (_attributes_separator) {
_attributes_separator->scene()->removeItem(_attributes_separator);
delete _attributes_separator;
_attributes_separator = 0;
}
// attributes
if (!_attributes_text.isEmpty()) {
if (!_attributes) {
_attributes = new QGraphicsTextItem(this);
}
_attributes->setFont(style->getNormalFont());
//_attributes->setBrush(style->getTextBrush());
_attributes->setDefaultTextColor(style->getTextBrush().color());
_attributes->setHtml(_attributes_text);
} else if (_attributes) {
_attributes->scene()->removeItem(_attributes);
delete _attributes;
_attributes = 0;
}
// methods separator
if (_shape || !_attributes_text.isEmpty() || !_methods_text.isEmpty()) {
if (!_methods_separator) {
_methods_separator = new QGraphicsLineItem(this);
}
_methods_separator->setPen(style->getInnerLinePen());
_methods_separator->setZValue(SHAPE_DETAILS_ZVALUE);
} else if (_methods_separator) {
_methods_separator->scene()->removeItem(_methods_separator);
delete _methods_separator;
_methods_separator = 0;
}
// methods
if (!_methods_text.isEmpty()) {
if (!_methods) {
_methods = new QGraphicsTextItem(this);
}
_methods->setFont(style->getNormalFont());
//_methods->setBrush(style->getTextBrush());
_methods->setDefaultTextColor(style->getTextBrush().color());
_methods->setHtml(_methods_text);
} else if (_methods) {
_methods->scene()->removeItem(_methods);
delete _methods;
_methods = 0;
}
// template parameters
if (template_display == DClass::TEMPLATE_BOX && !diagram_class->getTemplateParameters().isEmpty()) {
if (!_template_parameter_box) {
_template_parameter_box = new TemplateParameterBox(this);
}
QPen pen = style->getOuterLinePen();
pen.setStyle(Qt::DashLine);
_template_parameter_box->setPen(pen);
_template_parameter_box->setBrush(QBrush(Qt::white));
_template_parameter_box->setFont(style->getSmallFont());
_template_parameter_box->setTextBrush(style->getTextBrush());
_template_parameter_box->setTemplateParameters(diagram_class->getTemplateParameters());
} else if (_template_parameter_box) {
_template_parameter_box->scene()->removeItem(_template_parameter_box);
delete _template_parameter_box;
_template_parameter_box = 0;
}
updateSelectionMarker(_custom_icon);
// relation starters
if (isFocusSelected()) {
if (!_relation_starter) {
_relation_starter = new RelationStarter(this, getDiagramSceneModel(), 0);
scene()->addItem(_relation_starter);
_relation_starter->setZValue(RELATION_STARTER_ZVALUE);
_relation_starter->addArrow(QLatin1String("inheritance"), ArrowItem::SHAFT_SOLID, ArrowItem::HEAD_TRIANGLE);
_relation_starter->addArrow(QLatin1String("dependency"), ArrowItem::SHAFT_DASHED, ArrowItem::HEAD_OPEN);
_relation_starter->addArrow(QLatin1String("association"), ArrowItem::SHAFT_SOLID, ArrowItem::HEAD_FILLED_TRIANGLE);
}
} else if (_relation_starter) {
scene()->removeItem(_relation_starter);
delete _relation_starter;
_relation_starter = 0;
}
updateAlignmentButtons();
updateGeometry();
}
bool ClassItem::intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const
{
QPolygonF polygon;
if (_custom_icon) {
QRectF rect = getObject()->getRect();
// polygon = _custom_icon->path().toFillPolygon(QTransform()
// .scale(rect.width() / _custom_icon->getShapeWidth(), rect.height() / _custom_icon->getShapeHeight())
// .translate(getObject()->getPos().x(), getObject()->getPos().y()));
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
} else {
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
}
return GeometryUtilities::intersect(polygon, line, intersection_point, intersection_line);
}
QSizeF ClassItem::getMinimumSize() const
{
return calcMinimumGeometry();
}
QPointF ClassItem::getRelationStartPos() const
{
return pos();
}
void ClassItem::relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points)
{
DElement *target_element = getDiagramSceneModel()->findTopmostElement(to_scene_pos);
if (target_element) {
if (id == QLatin1String("inheritance")) {
DClass *base_class = dynamic_cast<DClass *>(target_element);
if (base_class) {
DClass *derived_class = dynamic_cast<DClass *>(getObject());
QMT_CHECK(derived_class);
getDiagramSceneModel()->getDiagramSceneController()->createInheritance(derived_class, base_class, intermediate_points, getDiagramSceneModel()->getDiagram());
}
} else if (id == QLatin1String("dependency")) {
DObject *dependant_object = dynamic_cast<DObject *>(target_element);
if (dependant_object) {
getDiagramSceneModel()->getDiagramSceneController()->createDependency(getObject(), dependant_object, intermediate_points, getDiagramSceneModel()->getDiagram());
}
} else if (id == QLatin1String("association")) {
DClass *assoziated_class = dynamic_cast<DClass *>(target_element);
if (assoziated_class) {
DClass *derived_class = dynamic_cast<DClass *>(getObject());
QMT_CHECK(derived_class);
getDiagramSceneModel()->getDiagramSceneController()->createAssociation(derived_class, assoziated_class, intermediate_points, getDiagramSceneModel()->getDiagram());
}
}
}
}
bool ClassItem::extendContextMenu(QMenu *menu)
{
bool extended = false;
if (getDiagramSceneModel()->getDiagramSceneController()->getElementTasks()->hasClassDefinition(getObject(), getDiagramSceneModel()->getDiagram())) {
menu->addAction(new ContextMenuAction(QObject::tr("Show Definition"), QStringLiteral("showDefinition"), menu));
extended = true;
}
return extended;
}
bool ClassItem::handleSelectedContextMenuAction(QAction *action)
{
ContextMenuAction *klass_action = dynamic_cast<ContextMenuAction *>(action);
if (klass_action) {
if (klass_action->getId() == QStringLiteral("showDefinition")) {
getDiagramSceneModel()->getDiagramSceneController()->getElementTasks()->openClassDefinition(getObject(), getDiagramSceneModel()->getDiagram());
return true;
}
}
return false;
}
QSizeF ClassItem::calcMinimumGeometry() const
{
double width = 0.0;
double height = 0.0;
if (_custom_icon) {
return getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT);
}
height += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
width = std::max(width, stereotype_icon_item->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += stereotype_icon_item->boundingRect().height();
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
width = std::max(width, stereotypes_item->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += stereotypes_item->boundingRect().height();
}
if (_namespace) {
width = std::max(width, _namespace->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += _namespace->boundingRect().height();
}
if (_class_name) {
width = std::max(width, _class_name->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += _class_name->boundingRect().height();
}
if (_context_label) {
height += _context_label->getHeight();
}
if (_attributes_separator) {
height += 8.0;
}
if (_attributes) {
width = std::max(width, _attributes->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += _attributes->boundingRect().height();
}
if (_methods_separator) {
height += 8.0;
}
if (_methods) {
width = std::max(width, _methods->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += _methods->boundingRect().height();
}
height += BODY_VERT_BORDER;
return GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT);
}
void ClassItem::updateGeometry()
{
prepareGeometryChange();
// calc width and height
double width = 0.0;
double height = 0.0;
QSizeF geometry = calcMinimumGeometry();
width = geometry.width();
height = geometry.height();
if (getObject()->hasAutoSize()) {
if (!_custom_icon) {
if (width < MINIMUM_AUTO_WIDTH) {
width = MINIMUM_AUTO_WIDTH;
}
if (height < MINIMUM_AUTO_HEIGHT) {
height = MINIMUM_AUTO_HEIGHT;
}
}
} else {
QRectF rect = getObject()->getRect();
if (rect.width() > width) {
width = rect.width();
}
if (rect.height() > height) {
height = rect.height();
}
}
// update sizes and positions
double left = -width / 2.0;
double right = width / 2.0;
double top = -height / 2.0;
//double bottom = height / 2.0;
double y = top;
setPos(getObject()->getPos());
QRectF rect(left, top, width, height);
// the object is updated without calling DiagramController intentionally.
// attribute rect is not a real attribute stored on DObject but
// a backup for the graphics item used for manual resized and persistency.
getObject()->setRect(rect);
if (_custom_icon) {
_custom_icon->setPos(left, top);
_custom_icon->setActualSize(QSizeF(width, height));
y += height;
}
if (_shape) {
_shape->setRect(rect);
}
y += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
stereotype_icon_item->setPos(right - stereotype_icon_item->boundingRect().width() - BODY_HORIZ_BORDER, y);
y += stereotype_icon_item->boundingRect().height();
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
stereotypes_item->setPos(-stereotypes_item->boundingRect().width() / 2.0, y);
y += stereotypes_item->boundingRect().height();
}
if (_namespace) {
_namespace->setPos(-_namespace->boundingRect().width() / 2.0, y);
y += _namespace->boundingRect().height();
}
if (_class_name) {
_class_name->setPos(-_class_name->boundingRect().width() / 2.0, y);
y += _class_name->boundingRect().height();
}
if (_context_label) {
if (_custom_icon) {
_context_label->resetMaxWidth();
} else {
_context_label->setMaxWidth(width - 2 * BODY_HORIZ_BORDER);
}
_context_label->setPos(-_context_label->boundingRect().width() / 2.0, y);
y += _context_label->boundingRect().height();
}
if (_attributes_separator) {
_attributes_separator->setLine(left, 4.0, right, 4.0);
_attributes_separator->setPos(0, y);
y += 8.0;
}
if (_attributes) {
if (_custom_icon) {
_attributes->setPos(-_attributes->boundingRect().width() / 2.0, y);
} else {
_attributes->setPos(left + BODY_HORIZ_BORDER, y);
}
y += _attributes->boundingRect().height();
}
if (_methods_separator) {
_methods_separator->setLine(left, 4.0, right, 4.0);
_methods_separator->setPos(0, y);
y += 8.0;
}
if (_methods) {
if (_custom_icon) {
_methods->setPos(-_methods->boundingRect().width() / 2.0, y);
} else {
_methods->setPos(left + BODY_HORIZ_BORDER, y);
}
y += _methods->boundingRect().height();
}
if (_template_parameter_box) {
_template_parameter_box->setBreakLines(false);
double x = right - _template_parameter_box->boundingRect().width() * 0.8;
if (x < 0) {
_template_parameter_box->setBreakLines(true);
x = right - _template_parameter_box->boundingRect().width() * 0.8;
}
if (x < 0) {
x = 0;
}
_template_parameter_box->setPos(x, top - _template_parameter_box->boundingRect().height() + BODY_VERT_BORDER);
}
updateSelectionMarkerGeometry(rect);
if (_relation_starter) {
_relation_starter->setPos(mapToScene(QPointF(right + 8.0, top)));
}
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
void ClassItem::updateMembers(const Style *style)
{
Q_UNUSED(style)
_attributes_text.clear();
_methods_text.clear();
MClassMember::Visibility attributes_visibility = MClassMember::VISIBILITY_UNDEFINED;
MClassMember::Visibility methods_visibility = MClassMember::VISIBILITY_UNDEFINED;
QString attributes_group;
QString methods_group;
MClassMember::Visibility *current_visibility = 0;
QString *current_group = 0;
QString *text = 0;
DClass *dclass = dynamic_cast<DClass *>(getObject());
QMT_CHECK(dclass);
// TODO move bool have_icon_fonts into class Style?
bool have_icon_fonts = false; // style->getNormalFont().family() == QStringLiteral("Modelling");
// TODO any reason to show visibility as group instead of per member?
bool use_group_visibility = false;
foreach (const MClassMember &member, dclass->getMembers()) {
switch (member.getMemberType()) {
case MClassMember::MEMBER_UNDEFINED:
QMT_CHECK(false);
break;
case MClassMember::MEMBER_ATTRIBUTE:
current_visibility = &attributes_visibility;
current_group = &attributes_group;
text = &_attributes_text;
break;
case MClassMember::MEMBER_METHOD:
current_visibility = &methods_visibility;
current_group = &methods_group;
text = &_methods_text;
break;
}
if (!text->isEmpty()) {
*text += QStringLiteral("<br/>");
}
bool add_newline = false;
bool add_space = false;
if (member.getVisibility() != *current_visibility) {
if (use_group_visibility) {
if (member.getVisibility() != MClassMember::VISIBILITY_UNDEFINED) {
QString vis;
switch (member.getVisibility()) {
case MClassMember::VISIBILITY_UNDEFINED:
break;
case MClassMember::VISIBILITY_PUBLIC:
vis = QStringLiteral("public:");
break;
case MClassMember::VISIBILITY_PROTECTED:
vis = QStringLiteral("protected:");
break;
case MClassMember::VISIBILITY_PRIVATE:
vis = QStringLiteral("private:");
break;
case MClassMember::VISIBILITY_SIGNALS:
vis = QStringLiteral("signals:");
break;
case MClassMember::VISIBILITY_PRIVATE_SLOTS:
vis = QStringLiteral("private slots:");
break;
case MClassMember::VISIBILITY_PROTECTED_SLOTS:
vis = QStringLiteral("protected slots:");
break;
case MClassMember::VISIBILITY_PUBLIC_SLOTS:
vis = QStringLiteral("public slots:");
break;
}
*text += vis;
add_newline = true;
add_space = true;
}
}
*current_visibility = member.getVisibility();
}
if (member.getGroup() != current_group) {
if (add_space) {
*text += QStringLiteral(" ");
}
*text += QString(QStringLiteral("[%1]")).arg(member.getGroup());
add_newline = true;
*current_group = member.getGroup();
}
if (add_newline) {
*text += QStringLiteral("<br/>");
}
add_space = false;
bool have_signal = false;
bool have_slot = false;
if (!use_group_visibility) {
if (member.getVisibility() != MClassMember::VISIBILITY_UNDEFINED) {
QString vis;
switch (member.getVisibility()) {
case MClassMember::VISIBILITY_UNDEFINED:
break;
case MClassMember::VISIBILITY_PUBLIC:
vis = have_icon_fonts ? QString(QChar(0xe990)) : QStringLiteral("+");
add_space = true;
break;
case MClassMember::VISIBILITY_PROTECTED:
vis = have_icon_fonts ? QString(QChar(0xe98e)) : QStringLiteral("#");
add_space = true;
break;
case MClassMember::VISIBILITY_PRIVATE:
vis = have_icon_fonts ? QString(QChar(0xe98f)) : QStringLiteral("-");
add_space = true;
break;
case MClassMember::VISIBILITY_SIGNALS:
vis = have_icon_fonts ? QString(QChar(0xe994)) : QStringLiteral(">");
have_signal = true;
add_space = true;
break;
case MClassMember::VISIBILITY_PRIVATE_SLOTS:
vis = have_icon_fonts ? QString(QChar(0xe98f)) + QChar(0xe9cb)
: QStringLiteral("-$");
have_slot = true;
add_space = true;
break;
case MClassMember::VISIBILITY_PROTECTED_SLOTS:
vis = have_icon_fonts ? QString(QChar(0xe98e)) + QChar(0xe9cb)
: QStringLiteral("#$");
have_slot = true;
add_space = true;
break;
case MClassMember::VISIBILITY_PUBLIC_SLOTS:
vis = have_icon_fonts ? QString(QChar(0xe990)) + QChar(0xe9cb)
: QStringLiteral("+$");
have_slot = true;
add_space = true;
break;
}
*text += vis;
}
}
if (member.getProperties() & MClassMember::PROPERTY_QSIGNAL && !have_signal) {
*text += have_icon_fonts ? QString(QChar(0xe994)) : QStringLiteral(">");
add_space = true;
}
if (member.getProperties() & MClassMember::PROPERTY_QSLOT && !have_slot) {
*text += have_icon_fonts ? QString(QChar(0xe9cb)) : QStringLiteral("$");
add_space = true;
}
if (add_space) {
*text += QStringLiteral(" ");
}
if (member.getProperties() & MClassMember::PROPERTY_QINVOKABLE) {
*text += QStringLiteral("invokable ");
}
if (!member.getStereotypes().isEmpty()) {
*text += StereotypesItem::format(member.getStereotypes());
*text += QStringLiteral(" ");
}
if (member.getProperties() & MClassMember::PROPERTY_VIRTUAL) {
*text += QStringLiteral("virtual ");
}
*text += member.getDeclaration();
if (member.getProperties() & MClassMember::PROPERTY_CONST) {
*text += QStringLiteral(" const");
}
if (member.getProperties() & MClassMember::PROPERTY_OVERRIDE) {
*text += QStringLiteral(" override");
}
if (member.getProperties() & MClassMember::PROPERTY_FINAL) {
*text += QStringLiteral(" final");
}
if (member.getProperties() & MClassMember::PROPERTY_ABSTRACT) {
*text += QStringLiteral(" = 0");
}
}
}
}

View File

@@ -0,0 +1,129 @@
/***************************************************************************
**
** 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 QMT_GRAPHICSCLASSITEM_H
#define QMT_GRAPHICSCLASSITEM_H
#include "objectitem.h"
#include "qmt/diagram_scene/capabilities/relationable.h"
QT_BEGIN_NAMESPACE
class QGraphicsRectItem;
class QGraphicsSimpleTextItem;
class QGraphicsLineItem;
class QGraphicsTextItem;
QT_END_NAMESPACE
namespace qmt {
class DiagramSceneModel;
class DClass;
class CustomIconItem;
class ContextLabelItem;
class TemplateParameterBox;
class RelationStarter;
class Style;
class ClassItem :
public ObjectItem,
public IRelationable
{
public:
ClassItem(DClass *klass, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~ClassItem();
public:
void update();
public:
bool intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const;
public:
QSizeF getMinimumSize() const;
public:
QPointF getRelationStartPos() const;
void relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points);
protected:
bool extendContextMenu(QMenu *menu);
bool handleSelectedContextMenuAction(QAction *action);
private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
void updateMembers(const Style *style);
private:
CustomIconItem *_custom_icon;
QGraphicsRectItem *_shape;
QGraphicsSimpleTextItem *_namespace;
QGraphicsSimpleTextItem *_class_name;
ContextLabelItem *_context_label;
QGraphicsLineItem *_attributes_separator;
QString _attributes_text;
QGraphicsTextItem *_attributes;
QGraphicsLineItem *_methods_separator;
QString _methods_text;
QGraphicsTextItem *_methods;
TemplateParameterBox *_template_parameter_box;
RelationStarter *_relation_starter;
};
}
#endif // QMT_GRAPHICSCLASSITEM_H

View File

@@ -0,0 +1,424 @@
/***************************************************************************
**
** 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 "componentitem.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram/dcomponent.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/contextlabelitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/stereotype/stereotypeicon.h"
#include "qmt/style/style.h"
#include "qmt/tasks/diagramscenecontroller.h"
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsSimpleTextItem>
#include <QBrush>
#include <QPen>
#include <QFont>
#include <algorithm>
namespace qmt {
static const qreal RECT_HEIGHT = 15.0;
static const qreal RECT_WIDTH = 45.0;
static const qreal UPPER_RECT_Y = 10.0;
static const qreal RECT_Y_DISTANCE = 10.0;
static const qreal LOWER_RECT_MIN_Y = 10.0;
static const qreal BODY_VERT_BORDER = 4.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
ComponentItem::ComponentItem(DComponent *component, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: ObjectItem(component, diagram_scene_model, parent),
_custom_icon(0),
_shape(0),
_upper_rect(0),
_lower_rect(0),
_component_name(0),
_context_label(0),
_relation_starter(0)
{
}
ComponentItem::~ComponentItem()
{
}
void ComponentItem::update()
{
prepareGeometryChange();
updateStereotypeIconDisplay();
const Style *style = getAdaptedStyle(getStereotypeIconId());
// custom icon
if (getStereotypeIconDisplay() == StereotypeIcon::DISPLAY_ICON) {
if (!_custom_icon) {
_custom_icon = new CustomIconItem(getDiagramSceneModel(), this);
}
_custom_icon->setStereotypeIconId(getStereotypeIconId());
_custom_icon->setBaseSize(getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT));
_custom_icon->setBrush(style->getFillBrush());
_custom_icon->setPen(style->getOuterLinePen());
_custom_icon->setZValue(SHAPE_ZVALUE);
} else if (_custom_icon) {
_custom_icon->scene()->removeItem(_custom_icon);
delete _custom_icon;
_custom_icon = 0;
}
// shape
bool delete_rects = false;
if (!_custom_icon) {
if (!_shape) {
_shape = new QGraphicsRectItem(this);
}
_shape->setBrush(style->getFillBrush());
_shape->setPen(style->getOuterLinePen());
_shape->setZValue(SHAPE_ZVALUE);
if (!hasPlainShape()) {
if (!_upper_rect) {
_upper_rect = new QGraphicsRectItem(this);
}
_upper_rect->setBrush(style->getFillBrush());
_upper_rect->setPen(style->getOuterLinePen());
_upper_rect->setZValue(SHAPE_DETAILS_ZVALUE);
if (!_lower_rect) {
_lower_rect = new QGraphicsRectItem(this);
}
_lower_rect->setBrush(style->getFillBrush());
_lower_rect->setPen(style->getOuterLinePen());
_lower_rect->setZValue(SHAPE_DETAILS_ZVALUE);
} else {
delete_rects = true;
}
} else {
delete_rects = true;
if (_shape) {
_shape->scene()->removeItem(_shape);
delete _shape;
_shape = 0;
}
}
if (delete_rects) {
if (_lower_rect) {
_lower_rect->scene()->removeItem(_lower_rect);
delete _lower_rect;
_lower_rect = 0;
}
if (_upper_rect) {
_upper_rect->scene()->removeItem(_upper_rect);
delete _upper_rect;
_upper_rect = 0;
}
}
// stereotypes
updateStereotypes(getStereotypeIconId(), getStereotypeIconDisplay(), style);
// component name
if (!_component_name) {
_component_name = new QGraphicsSimpleTextItem(this);
}
_component_name->setFont(style->getHeaderFont());
_component_name->setBrush(style->getTextBrush());
_component_name->setText(getObject()->getName());
// context
if (showContext()) {
if (!_context_label) {
_context_label = new ContextLabelItem(this);
}
_context_label->setFont(style->getSmallFont());
_context_label->setBrush(style->getTextBrush());
_context_label->setContext(getObject()->getContext());
} else if (_context_label) {
_context_label->scene()->removeItem(_context_label);
delete _context_label;
_context_label = 0;
}
updateSelectionMarker(_custom_icon);
// relation starters
if (isFocusSelected()) {
if (!_relation_starter && scene()) {
_relation_starter = new RelationStarter(this, getDiagramSceneModel(), 0);
scene()->addItem(_relation_starter);
_relation_starter->setZValue(RELATION_STARTER_ZVALUE);
_relation_starter->addArrow(QStringLiteral("dependency"), ArrowItem::SHAFT_DASHED, ArrowItem::HEAD_OPEN);
}
} else if (_relation_starter) {
if (_relation_starter->scene()) {
_relation_starter->scene()->removeItem(_relation_starter);
}
delete _relation_starter;
_relation_starter = 0;
}
updateAlignmentButtons();
updateGeometry();
}
bool ComponentItem::intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const
{
QPolygonF polygon;
if (_custom_icon) {
// TODO use custom_icon path as shape
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
} else if (hasPlainShape()){
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
} else {
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft()
<< rect.topRight()
<< rect.bottomRight()
<< rect.bottomLeft()
<< rect.bottomLeft() + QPointF(0, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT)
<< rect.bottomLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT)
<< rect.bottomLeft() + QPointF(-RECT_WIDTH * 0.5, UPPER_RECT_Y)
<< rect.bottomLeft() + QPointF(0, UPPER_RECT_Y)
<< rect.topLeft();
}
return GeometryUtilities::intersect(polygon, line, intersection_point, intersection_line);
}
QSizeF ComponentItem::getMinimumSize() const
{
return calcMinimumGeometry();
}
QList<ILatchable::Latch> ComponentItem::getHorizontalLatches(ILatchable::Action action, bool grabbed_item) const
{
return ObjectItem::getHorizontalLatches(action, grabbed_item);
}
QList<ILatchable::Latch> ComponentItem::getVerticalLatches(ILatchable::Action action, bool grabbed_item) const
{
return ObjectItem::getVerticalLatches(action, grabbed_item);
}
#if 0
QList<qreal> ComponentItem::getHorizontalLatches() const
{
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
return QList<qreal>() << (rect.left() - RECT_WIDTH * 0.5) << rect.left() << rect.right();
}
QList<qreal> ComponentItem::getVerticalLatches() const
{
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
return QList<qreal>() << rect.top() << rect.bottom();
}
#endif
QPointF ComponentItem::getRelationStartPos() const
{
return pos();
}
void ComponentItem::relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points)
{
DElement *target_element = getDiagramSceneModel()->findTopmostElement(to_scene_pos);
if (target_element) {
if (id == QStringLiteral("dependency")) {
DObject *dependant_object = dynamic_cast<DObject *>(target_element);
if (dependant_object) {
getDiagramSceneModel()->getDiagramSceneController()->createDependency(getObject(), dependant_object, intermediate_points, getDiagramSceneModel()->getDiagram());
}
}
}
}
bool ComponentItem::hasPlainShape() const
{
DComponent *diagram_component = dynamic_cast<DComponent *>(getObject());
QMT_CHECK(diagram_component);
return diagram_component->getPlainShape();
}
QSizeF ComponentItem::calcMinimumGeometry() const
{
double width = 0.0;
double height = 0.0;
if (_custom_icon) {
return getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT);
}
height += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
width = std::max(width, stereotype_icon_item->boundingRect().width());
height += stereotype_icon_item->boundingRect().height();
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
width = std::max(width, stereotypes_item->boundingRect().width());
height += stereotypes_item->boundingRect().height();
}
if (_component_name) {
width = std::max(width, _component_name->boundingRect().width());
height += _component_name->boundingRect().height();
}
if (_context_label) {
height += _context_label->getHeight();
}
height += BODY_VERT_BORDER;
if (!hasPlainShape()) {
width = RECT_WIDTH * 0.5 + BODY_HORIZ_BORDER + width + BODY_HORIZ_BORDER + RECT_WIDTH * 0.5;
double min_height = UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT + LOWER_RECT_MIN_Y;
if (height < min_height) {
height = min_height;
}
} else {
width = BODY_HORIZ_BORDER + width + BODY_HORIZ_BORDER;
}
return GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT);
}
void ComponentItem::updateGeometry()
{
prepareGeometryChange();
// calc width and height
double width = 0.0;
double height = 0.0;
QSizeF geometry = calcMinimumGeometry();
width = geometry.width();
height = geometry.height();
if (getObject()->hasAutoSize()) {
// nothing
} else {
QRectF rect = getObject()->getRect();
if (rect.width() > width) {
width = rect.width();
}
if (rect.height() > height) {
height = rect.height();
}
}
// update sizes and positions
double left = -width / 2.0;
double right = width / 2.0;
double top = -height / 2.0;
//double bottom = height / 2.0;
double y = top;
setPos(getObject()->getPos());
QRectF rect(left, top, width, height);
// the object is updated without calling DiagramController intentionally.
// attribute rect is not a real attribute stored on DObject but
// a backup for the graphics item used for manual resized and persistency.
getObject()->setRect(rect);
if (_custom_icon) {
_custom_icon->setPos(left, top);
_custom_icon->setActualSize(QSizeF(width, height));
y += height;
}
if (_shape) {
_shape->setRect(rect);
}
if (_upper_rect) {
QRectF upper_rect(0, 0, RECT_WIDTH, RECT_HEIGHT);
_upper_rect->setRect(upper_rect);
_upper_rect->setPos(left - RECT_WIDTH * 0.5, top + UPPER_RECT_Y);
}
if (_lower_rect) {
QRectF lower_rect(0, 0, RECT_WIDTH, RECT_HEIGHT);
_lower_rect->setRect(lower_rect);
_lower_rect->setPos(left - RECT_WIDTH * 0.5, top + UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE);
}
y += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
stereotype_icon_item->setPos(right - stereotype_icon_item->boundingRect().width() - BODY_HORIZ_BORDER, y);
y += stereotype_icon_item->boundingRect().height();
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
stereotypes_item->setPos(-stereotypes_item->boundingRect().width() / 2.0, y);
y += stereotypes_item->boundingRect().height();
}
if (_component_name) {
_component_name->setPos(-_component_name->boundingRect().width() / 2.0, y);
y += _component_name->boundingRect().height();
}
if (_context_label) {
if (_custom_icon) {
_context_label->resetMaxWidth();
} else {
double max_context_width = width - 2 * BODY_HORIZ_BORDER - (hasPlainShape() ? 0 : RECT_WIDTH);
_context_label->setMaxWidth(max_context_width);
}
_context_label->setPos(-_context_label->boundingRect().width() / 2.0, y);
y += _context_label->boundingRect().height();
}
updateSelectionMarkerGeometry(rect);
if (_relation_starter) {
_relation_starter->setPos(mapToScene(QPointF(right + 8.0, top)));
}
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
}

View File

@@ -0,0 +1,115 @@
/***************************************************************************
**
** 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 QMT_GRAPHICSCOMPONENTITEM_H
#define QMT_GRAPHICSCOMPONENTITEM_H
#include "objectitem.h"
#include "qmt/diagram_scene/capabilities/relationable.h"
QT_BEGIN_NAMESPACE
class QGraphicsRectItem;
class QGraphicsSimpleTextItem;
class QGraphicsLineItem;
QT_END_NAMESPACE
namespace qmt {
class DiagramSceneModel;
class DComponent;
class CustomIconItem;
class ContextLabelItem;
class RelationStarter;
class ComponentItem :
public ObjectItem,
public IRelationable
{
public:
ComponentItem(DComponent *component, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~ComponentItem();
public:
void update();
public:
bool intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const;
public:
QSizeF getMinimumSize() const;
public:
QList<Latch> getHorizontalLatches(Action action, bool grabbed_item) const;
QList<Latch> getVerticalLatches(Action action, bool grabbed_item) const;
public:
QPointF getRelationStartPos() const;
void relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points);
private:
bool hasPlainShape() const;
QSizeF calcMinimumGeometry() const;
void updateGeometry();
private:
CustomIconItem *_custom_icon;
QGraphicsRectItem *_shape;
QGraphicsRectItem *_upper_rect;
QGraphicsRectItem *_lower_rect;
QGraphicsSimpleTextItem *_component_name;
ContextLabelItem *_context_label;
RelationStarter *_relation_starter;
};
}
#endif // QMT_GRAPHICSCOMPONENTITEM_H

View File

@@ -0,0 +1,292 @@
/***************************************************************************
**
** 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 "diagramitem.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/stereotype/stereotypeicon.h"
#include "qmt/style/style.h"
#include "qmt/tasks/diagramscenecontroller.h"
#include <QGraphicsScene>
#include <QPointF>
#include <QFont>
#include <QBrush>
#include <QPen>
namespace qmt {
static const qreal MINIMUM_AUTO_WIDTH = 60.0;
static const qreal MINIMUM_AUTO_HEIGHT = 60.0;
static const qreal MINIMUM_WIDTH = 40.0;
static const qreal FOLD_WIDTH = 15.0;
static const qreal FOLD_HEIGHT = 15.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
static const qreal BODY_VERT_BORDER = 4.0;
DiagramItem::DiagramItem(DDiagram *diagram, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: ObjectItem(diagram, diagram_scene_model, parent),
_custom_icon(0),
_body(0),
_fold(0),
_diagram_name(0)
{
}
DiagramItem::~DiagramItem()
{
}
void DiagramItem::update()
{
prepareGeometryChange();
updateStereotypeIconDisplay();
const Style *style = getAdaptedStyle(getStereotypeIconId());
// custom icon
if (getStereotypeIconDisplay() == StereotypeIcon::DISPLAY_ICON) {
if (!_custom_icon) {
_custom_icon = new CustomIconItem(getDiagramSceneModel(), this);
}
_custom_icon->setStereotypeIconId(getStereotypeIconId());
_custom_icon->setBaseSize(getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT));
_custom_icon->setBrush(style->getFillBrush());
_custom_icon->setPen(style->getOuterLinePen());
_custom_icon->setZValue(SHAPE_ZVALUE);
} else if (_custom_icon) {
_custom_icon->scene()->removeItem(_custom_icon);
delete _custom_icon;
_custom_icon = 0;
}
// shape
if (!_custom_icon) {
if (!_body) {
_body = new QGraphicsPolygonItem(this);
}
_body->setBrush(style->getFillBrush());
_body->setPen(style->getOuterLinePen());
_body->setZValue(SHAPE_ZVALUE);
if (!_fold) {
_fold = new QGraphicsPolygonItem(this);
}
_fold->setBrush(style->getExtraFillBrush());
_fold->setPen(style->getOuterLinePen());
_fold->setZValue(SHAPE_DETAILS_ZVALUE);
} else {
if (_fold) {
_fold->scene()->removeItem(_fold);
delete _fold;
_fold = 0;
}
if (_body) {
_body->scene()->removeItem(_body);
delete _body;
_body = 0;
}
}
// stereotypes
updateStereotypes(getStereotypeIconId(), getStereotypeIconDisplay(), style);
// diagram name
if (!_diagram_name) {
_diagram_name = new QGraphicsSimpleTextItem(this);
}
_diagram_name->setFont(style->getHeaderFont());
_diagram_name->setBrush(style->getTextBrush());
_diagram_name->setText(getObject()->getName());
updateSelectionMarker(_custom_icon);
updateAlignmentButtons();
updateGeometry();
}
bool DiagramItem::intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const
{
QPolygonF polygon;
if (_custom_icon) {
// TODO use custom_icon path as shape
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
} else {
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
}
return GeometryUtilities::intersect(polygon, line, intersection_point, intersection_line);
}
QSizeF DiagramItem::getMinimumSize() const
{
return calcMinimumGeometry();
}
QSizeF DiagramItem::calcMinimumGeometry() const
{
double width = MINIMUM_WIDTH;
double height = 0.0;
if (_custom_icon) {
return getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT);
}
height += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
width = std::max(width, stereotype_icon_item->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += std::max(FOLD_HEIGHT, stereotype_icon_item->boundingRect().height());
} else {
height += FOLD_HEIGHT;
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
width = std::max(width, stereotypes_item->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += stereotypes_item->boundingRect().height();
}
if (_diagram_name) {
width = std::max(width, _diagram_name->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
height += _diagram_name->boundingRect().height();
}
height += BODY_VERT_BORDER;
return GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT);
}
void DiagramItem::updateGeometry()
{
prepareGeometryChange();
// calc width and height
double width = 0.0;
double height = 0.0;
QSizeF geometry = calcMinimumGeometry();
width = geometry.width();
height = geometry.height();
if (getObject()->hasAutoSize()) {
if (!_custom_icon) {
if (width < MINIMUM_AUTO_WIDTH) {
width = MINIMUM_AUTO_WIDTH;
}
if (height < MINIMUM_AUTO_HEIGHT) {
height = MINIMUM_AUTO_HEIGHT;
}
}
} else {
QRectF rect = getObject()->getRect();
if (rect.width() > width) {
width = rect.width();
}
if (rect.height() > height) {
height = rect.height();
}
}
// update sizes and positions
double left = -width / 2.0;
//double right = width / 2.0;
double top = -height / 2.0;
//double bottom = height / 2.0;
double y = top;
setPos(getObject()->getPos());
QRectF rect(left, top, width, height);
// the object is updated without calling DiagramController intentionally.
// attribute rect is not a real attribute stored on DObject but
// a backup for the graphics item used for manual resized and persistency.
getObject()->setRect(rect);
if (_custom_icon) {
_custom_icon->setPos(left, top);
_custom_icon->setActualSize(QSizeF(width, height));
y += height;
}
if (_body) {
QPolygonF body_polygon;
body_polygon
<< rect.topLeft()
<< rect.topRight() + QPointF(-FOLD_WIDTH, 0.0)
<< rect.topRight() + QPointF(0.0, FOLD_HEIGHT)
<< rect.bottomRight()
<< rect.bottomLeft();
_body->setPolygon(body_polygon);
}
if (_fold) {
QPolygonF fold_polygon;
fold_polygon
<< rect.topRight() + QPointF(-FOLD_WIDTH, 0.0)
<< rect.topRight() + QPointF(0.0, FOLD_HEIGHT)
<< rect.topRight() + QPointF(-FOLD_WIDTH, FOLD_HEIGHT);
_fold->setPolygon(fold_polygon);
}
y += BODY_VERT_BORDER;
if (!_custom_icon) {
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
stereotype_icon_item->setPos(left + BODY_HORIZ_BORDER, y);
y += std::max(FOLD_HEIGHT, stereotype_icon_item->boundingRect().height());
} else {
y += FOLD_HEIGHT;
}
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
stereotypes_item->setPos(-stereotypes_item->boundingRect().width() / 2.0, y);
y += stereotypes_item->boundingRect().height();
}
if (_diagram_name) {
_diagram_name->setPos(-_diagram_name->boundingRect().width() / 2.0, y);
y += _diagram_name->boundingRect().height();
}
updateSelectionMarkerGeometry(rect);
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
}

View File

@@ -0,0 +1,84 @@
/***************************************************************************
**
** 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 QMT_GRAPHICSDIAGRAMITEM_H
#define QMT_GRAPHICSDIAGRAMITEM_H
#include "objectitem.h"
namespace qmt {
class DDiagram;
class DiagramSceneModel;
class CustomIconItem;
class DiagramItem :
public ObjectItem
{
public:
explicit DiagramItem(DDiagram *diagram, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~DiagramItem();
public:
virtual void update();
public:
bool intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const;
public:
QSizeF getMinimumSize() const;
private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
private:
CustomIconItem *_custom_icon;
QGraphicsPolygonItem *_body;
QGraphicsPolygonItem *_fold;
QGraphicsSimpleTextItem *_diagram_name;
};
}
#endif // QMT_GRAPHICSDIAGRAMITEM_H

View File

@@ -0,0 +1,335 @@
/***************************************************************************
**
** 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 "itemitem.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram/ditem.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/contextlabelitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/stereotype/stereotypeicon.h"
#include "qmt/style/style.h"
#include "qmt/tasks/diagramscenecontroller.h"
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsSimpleTextItem>
#include <QBrush>
#include <QPen>
#include <QFont>
#include <algorithm>
namespace qmt {
static const qreal BODY_VERT_BORDER = 4.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
ItemItem::ItemItem(DItem *item, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: ObjectItem(item, diagram_scene_model, parent),
_custom_icon(0),
_shape(0),
_item_name(0),
_context_label(0),
_relation_starter(0)
{
}
ItemItem::~ItemItem()
{
}
void ItemItem::update()
{
prepareGeometryChange();
updateStereotypeIconDisplay();
DItem *diagram_item = dynamic_cast<DItem *>(getObject());
Q_UNUSED(diagram_item); // avoid warning about unsed variable
QMT_CHECK(diagram_item);
const Style *style = getAdaptedStyle(getShapeIconId());
if (!getShapeIconId().isEmpty()) {
if (!_custom_icon) {
_custom_icon = new CustomIconItem(getDiagramSceneModel(), this);
}
_custom_icon->setStereotypeIconId(getShapeIconId());
_custom_icon->setBaseSize(getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT));
_custom_icon->setBrush(style->getFillBrush());
_custom_icon->setPen(style->getOuterLinePen());
_custom_icon->setZValue(SHAPE_ZVALUE);
} else if (_custom_icon) {
_custom_icon->scene()->removeItem(_custom_icon);
delete _custom_icon;
_custom_icon = 0;
}
// shape
if (!_custom_icon) {
if (!_shape) {
_shape = new QGraphicsRectItem(this);
}
_shape->setBrush(style->getFillBrush());
_shape->setPen(style->getOuterLinePen());
_shape->setZValue(SHAPE_ZVALUE);
} else {
if (_shape) {
_shape->scene()->removeItem(_shape);
delete _shape;
_shape = 0;
}
}
// stereotypes
updateStereotypes(getStereotypeIconId(), getStereotypeIconDisplay(), getAdaptedStyle(getStereotypeIconId()));
// component name
if (!_item_name) {
_item_name = new QGraphicsSimpleTextItem(this);
}
_item_name->setFont(style->getHeaderFont());
_item_name->setBrush(style->getTextBrush());
_item_name->setText(getObject()->getName());
// context
if (showContext()) {
if (!_context_label) {
_context_label = new ContextLabelItem(this);
}
_context_label->setFont(style->getSmallFont());
_context_label->setBrush(style->getTextBrush());
_context_label->setContext(getObject()->getContext());
} else if (_context_label) {
_context_label->scene()->removeItem(_context_label);
delete _context_label;
_context_label = 0;
}
updateSelectionMarker(_custom_icon);
// relation starters
if (isFocusSelected()) {
if (!_relation_starter && scene()) {
_relation_starter = new RelationStarter(this, getDiagramSceneModel(), 0);
scene()->addItem(_relation_starter);
_relation_starter->setZValue(RELATION_STARTER_ZVALUE);
_relation_starter->addArrow(QStringLiteral("dependency"), ArrowItem::SHAFT_DASHED, ArrowItem::HEAD_OPEN);
}
} else if (_relation_starter) {
if (_relation_starter->scene()) {
_relation_starter->scene()->removeItem(_relation_starter);
}
delete _relation_starter;
_relation_starter = 0;
}
updateAlignmentButtons();
updateGeometry();
}
bool ItemItem::intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const
{
QPolygonF polygon;
if (_custom_icon) {
// TODO use custom_icon path as shape
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
} else {
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
}
return GeometryUtilities::intersect(polygon, line, intersection_point, intersection_line);
}
QSizeF ItemItem::getMinimumSize() const
{
return calcMinimumGeometry();
}
QList<ILatchable::Latch> ItemItem::getHorizontalLatches(ILatchable::Action action, bool grabbed_item) const
{
return ObjectItem::getHorizontalLatches(action, grabbed_item);
}
QList<ILatchable::Latch> ItemItem::getVerticalLatches(ILatchable::Action action, bool grabbed_item) const
{
return ObjectItem::getVerticalLatches(action, grabbed_item);
}
QPointF ItemItem::getRelationStartPos() const
{
return pos();
}
void ItemItem::relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points)
{
DElement *target_element = getDiagramSceneModel()->findTopmostElement(to_scene_pos);
if (target_element) {
if (id == QStringLiteral("dependency")) {
DObject *dependant_object = dynamic_cast<DObject *>(target_element);
if (dependant_object) {
getDiagramSceneModel()->getDiagramSceneController()->createDependency(getObject(), dependant_object, intermediate_points, getDiagramSceneModel()->getDiagram());
}
}
}
}
QSizeF ItemItem::calcMinimumGeometry() const
{
double width = 0.0;
double height = 0.0;
if (_custom_icon) {
return getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT);
}
height += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
width = std::max(width, stereotype_icon_item->boundingRect().width());
height += stereotype_icon_item->boundingRect().height();
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
width = std::max(width, stereotypes_item->boundingRect().width());
height += stereotypes_item->boundingRect().height();
}
if (_item_name) {
width = std::max(width, _item_name->boundingRect().width());
height += _item_name->boundingRect().height();
}
if (_context_label) {
height += _context_label->getHeight();
}
height += BODY_VERT_BORDER;
width = BODY_HORIZ_BORDER + width + BODY_HORIZ_BORDER;
return GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT);
}
void ItemItem::updateGeometry()
{
prepareGeometryChange();
// calc width and height
double width = 0.0;
double height = 0.0;
QSizeF geometry = calcMinimumGeometry();
width = geometry.width();
height = geometry.height();
if (getObject()->hasAutoSize()) {
// nothing
} else {
QRectF rect = getObject()->getRect();
if (rect.width() > width) {
width = rect.width();
}
if (rect.height() > height) {
height = rect.height();
}
}
// update sizes and positions
double left = -width / 2.0;
double right = width / 2.0;
double top = -height / 2.0;
//double bottom = height / 2.0;
double y = top;
setPos(getObject()->getPos());
QRectF rect(left, top, width, height);
// the object is updated without calling DiagramController intentionally.
// attribute rect is not a real attribute stored on DObject but
// a backup for the graphics item used for manual resized and persistency.
getObject()->setRect(rect);
if (_custom_icon) {
_custom_icon->setPos(left, top);
_custom_icon->setActualSize(QSizeF(width, height));
y += height;
}
if (_shape) {
_shape->setRect(rect);
}
y += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
stereotype_icon_item->setPos(right - stereotype_icon_item->boundingRect().width() - BODY_HORIZ_BORDER, y);
y += stereotype_icon_item->boundingRect().height();
}
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
stereotypes_item->setPos(-stereotypes_item->boundingRect().width() / 2.0, y);
y += stereotypes_item->boundingRect().height();
}
if (_item_name) {
_item_name->setPos(-_item_name->boundingRect().width() / 2.0, y);
y += _item_name->boundingRect().height();
}
if (_context_label) {
if (_custom_icon) {
_context_label->resetMaxWidth();
} else {
double max_context_width = width - 2 * BODY_HORIZ_BORDER;
_context_label->setMaxWidth(max_context_width);
}
_context_label->setPos(-_context_label->boundingRect().width() / 2.0, y);
y += _context_label->boundingRect().height();
}
updateSelectionMarkerGeometry(rect);
if (_relation_starter) {
_relation_starter->setPos(mapToScene(QPointF(right + 8.0, top)));
}
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
} // namespace qmt

View File

@@ -0,0 +1,109 @@
/***************************************************************************
**
** 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 QMT_ITEMITEM_H
#define QMT_ITEMITEM_H
#include "objectitem.h"
#include "qmt/diagram_scene/capabilities/relationable.h"
QT_BEGIN_NAMESPACE
class QGraphicsRectItem;
class QGraphicsSimpleTextItem;
class QGraphicsLineItem;
QT_END_NAMESPACE
namespace qmt {
class DiagramSceneModel;
class DItem;
class CustomIconItem;
class ContextLabelItem;
class RelationStarter;
class ItemItem :
public ObjectItem,
public IRelationable
{
public:
ItemItem(DItem *item, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~ItemItem();
public:
void update();
public:
bool intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const;
public:
QSizeF getMinimumSize() const;
public:
QList<Latch> getHorizontalLatches(Action action, bool grabbed_item) const;
QList<Latch> getVerticalLatches(Action action, bool grabbed_item) const;
public:
QPointF getRelationStartPos() const;
void relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points);
private:
QSizeF calcMinimumGeometry() const;
void updateGeometry();
private:
CustomIconItem *_custom_icon;
QGraphicsRectItem *_shape;
QGraphicsSimpleTextItem *_item_name;
ContextLabelItem *_context_label;
RelationStarter *_relation_starter;
};
} // namespace qmt
#endif // QMT_ITEMITEM_H

View File

@@ -0,0 +1,758 @@
/***************************************************************************
**
** 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 "objectitem.h"
#include "qmt/diagram/dobject.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram_controller/dselection.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/items/stereotypedisplayvisitor.h"
#include "qmt/diagram_scene/parts/alignbuttonsitem.h"
#include "qmt/diagram_scene/parts/rectangularselectionitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/contextmenuaction.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/mobject.h"
#include "qmt/model_controller/modelcontroller.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/style/style.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/styledobject.h"
#include "qmt/tasks/diagramscenecontroller.h"
#include "qmt/tasks/ielementtasks.h"
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <QCursor>
#include <QMenu>
#include <QDebug>
namespace qmt {
ObjectItem::ObjectItem(DObject *object, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: QGraphicsItem(parent),
_object(object),
_diagram_scene_model(diagram_scene_model),
_secondary_selected(false),
_focus_selected(false),
_stereotype_icon_display(StereotypeIcon::DISPLAY_LABEL),
_stereotypes(0),
_stereotype_icon(0),
_selection_marker(0),
_horizontal_align_buttons(0),
_vertical_align_buttons(0)
{
setFlags(QGraphicsItem::ItemIsSelectable);
}
ObjectItem::~ObjectItem()
{
}
QRectF ObjectItem::boundingRect() const
{
return childrenBoundingRect();
}
void ObjectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(painter);
Q_UNUSED(option);
Q_UNUSED(widget);
}
QPointF ObjectItem::getPos() const
{
return _object->getPos();
}
QRectF ObjectItem::getRect() const
{
return _object->getRect();
}
void ObjectItem::setPosAndRect(const QPointF &original_pos, const QRectF &original_rect, const QPointF &top_left_delta, const QPointF &bottom_right_delta)
{
QPointF new_pos = original_pos;
QRectF new_rect = original_rect;
GeometryUtilities::adjustPosAndRect(&new_pos, &new_rect, top_left_delta, bottom_right_delta, QPointF(0.5, 0.5));
if (new_pos != _object->getPos() || new_rect != _object->getRect()) {
_diagram_scene_model->getDiagramController()->startUpdateElement(_object, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_GEOMETRY);
_object->setPos(new_pos);
if (new_rect.size() != _object->getRect().size()) {
_object->setAutoSize(false);
}
_object->setRect(new_rect);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_object, _diagram_scene_model->getDiagram(), false);
}
}
void ObjectItem::alignItemSizeToRaster(IResizable::Side adjust_horizontal_side, IResizable::Side adjust_vertical_side, double raster_width, double raster_height)
{
QPointF pos = _object->getPos();
QRectF rect = _object->getRect();
double horiz_delta = rect.width() - qRound(rect.width() / raster_width) * raster_width;
double vert_delta = rect.height() - qRound(rect.height() / raster_height) * raster_height;
// make sure the new size is at least the minimum size
QSizeF minimum_size = getMinimumSize();
while (rect.width() + horiz_delta < minimum_size.width()) {
horiz_delta += raster_width;
}
while (rect.height() + vert_delta < minimum_size.height()) {
vert_delta += raster_height;
}
double left_delta = 0.0;
double right_delta = 0.0;
double top_delta = 0.0;
double bottom_delta = 0.0;
switch (adjust_horizontal_side) {
case IResizable::SIDE_NONE:
break;
case IResizable::SIDE_LEFT_OR_TOP:
left_delta = horiz_delta;
break;
case IResizable::SIDE_RIGHT_OR_BOTTOM:
right_delta = -horiz_delta;
break;
}
switch (adjust_vertical_side) {
case IResizable::SIDE_NONE:
break;
case IResizable::SIDE_LEFT_OR_TOP:
top_delta = vert_delta;
break;
case IResizable::SIDE_RIGHT_OR_BOTTOM:
bottom_delta = -vert_delta;
break;
}
QPointF top_left_delta(left_delta, top_delta);
QPointF bottom_right_delta(right_delta, bottom_delta);
setPosAndRect(pos, rect, top_left_delta, bottom_right_delta);
}
void ObjectItem::moveDelta(const QPointF &delta)
{
_diagram_scene_model->getDiagramController()->startUpdateElement(_object, _diagram_scene_model->getDiagram(), DiagramController::UPDATE_GEOMETRY);
_object->setPos(_object->getPos() + delta);
_diagram_scene_model->getDiagramController()->finishUpdateElement(_object, _diagram_scene_model->getDiagram(), false);
}
void ObjectItem::alignItemPositionToRaster(double raster_width, double raster_height)
{
QPointF pos = _object->getPos();
QRectF rect = _object->getRect();
QPointF top_left = pos + rect.topLeft();
double left_delta = qRound(top_left.x() / raster_width) * raster_width - top_left.x();
double top_delta = qRound(top_left.y() / raster_height) * raster_height - top_left.y();
QPointF top_left_delta(left_delta, top_delta);
setPosAndRect(pos, rect, top_left_delta, top_left_delta);
}
bool ObjectItem::isSecondarySelected() const
{
return _secondary_selected;
}
void ObjectItem::setSecondarySelected(bool secondary_selected)
{
if (_secondary_selected != secondary_selected) {
_secondary_selected = secondary_selected;
update();
}
}
bool ObjectItem::isFocusSelected() const
{
return _focus_selected;
}
void ObjectItem::setFocusSelected(bool focus_selected)
{
if (_focus_selected != focus_selected) {
_focus_selected = focus_selected;
update();
}
}
QList<ILatchable::Latch> ObjectItem::getHorizontalLatches(ILatchable::Action action, bool grabbed_item) const
{
Q_UNUSED(grabbed_item);
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
QList<ILatchable::Latch> result;
switch (action) {
case ILatchable::MOVE:
result << ILatchable::Latch(ILatchable::LEFT, rect.left(), rect.top(), rect.bottom(), QStringLiteral("left"))
<< ILatchable::Latch(ILatchable::HCENTER, rect.center().x(), rect.top(), rect.bottom(), QStringLiteral("center"))
<< ILatchable::Latch(ILatchable::RIGHT, rect.right(), rect.top(), rect.bottom(), QStringLiteral("right"));
break;
case ILatchable::RESIZE_LEFT:
result << ILatchable::Latch(ILatchable::LEFT, rect.left(), rect.top(), rect.bottom(), QStringLiteral("left"));
break;
case ILatchable::RESIZE_TOP:
QMT_CHECK(false);
break;
case ILatchable::RESIZE_RIGHT:
result << ILatchable::Latch(ILatchable::RIGHT, rect.right(), rect.top(), rect.bottom(), QStringLiteral("right"));
break;
case ILatchable::RESIZE_BOTTOM:
QMT_CHECK(false);
break;
}
return result;
}
QList<ILatchable::Latch> ObjectItem::getVerticalLatches(ILatchable::Action action, bool grabbed_item) const
{
Q_UNUSED(grabbed_item);
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
QList<ILatchable::Latch> result;
switch (action) {
case ILatchable::MOVE:
result << ILatchable::Latch(ILatchable::TOP, rect.top(), rect.left(), rect.right(), QStringLiteral("top"))
<< ILatchable::Latch(ILatchable::VCENTER, rect.center().y(), rect.left(), rect.right(), QStringLiteral("center"))
<< ILatchable::Latch(ILatchable::BOTTOM, rect.bottom(), rect.left(), rect.right(), QStringLiteral("bottom"));
break;
case ILatchable::RESIZE_LEFT:
QMT_CHECK(false);
break;
case ILatchable::RESIZE_TOP:
result << ILatchable::Latch(ILatchable::TOP, rect.top(), rect.left(), rect.right(), QStringLiteral("top"));
break;
case ILatchable::RESIZE_RIGHT:
QMT_CHECK(false);
break;
case ILatchable::RESIZE_BOTTOM:
result << ILatchable::Latch(ILatchable::BOTTOM, rect.bottom(), rect.left(), rect.right(), QStringLiteral("bottom"));
break;
}
return result;
}
void ObjectItem::align(IAlignable::AlignType align_type, const QString &identifier)
{
Q_UNUSED(identifier); // avoid warning in release mode
// subclasses may support other identifiers than the standard ones.
// but this implementation does not. So assert the names.
switch (align_type) {
case IAlignable::ALIGN_LEFT:
QMT_CHECK(identifier == QStringLiteral("left"));
_diagram_scene_model->getDiagramSceneController()->alignLeft(_object, _diagram_scene_model->getSelectedElements(), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_RIGHT:
QMT_CHECK(identifier == QStringLiteral("right"));
_diagram_scene_model->getDiagramSceneController()->alignRight(_object, _diagram_scene_model->getSelectedElements(), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_TOP:
QMT_CHECK(identifier == QStringLiteral("top"));
_diagram_scene_model->getDiagramSceneController()->alignTop(_object, _diagram_scene_model->getSelectedElements(), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_BOTTOM:
QMT_CHECK(identifier == QStringLiteral("bottom"));
_diagram_scene_model->getDiagramSceneController()->alignBottom(_object, _diagram_scene_model->getSelectedElements(), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_HCENTER:
QMT_CHECK(identifier == QStringLiteral("center"));
_diagram_scene_model->getDiagramSceneController()->alignHCenter(_object, _diagram_scene_model->getSelectedElements(), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_VCENTER:
QMT_CHECK(identifier == QStringLiteral("center"));
_diagram_scene_model->getDiagramSceneController()->alignVCenter(_object, _diagram_scene_model->getSelectedElements(), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_WIDTH:
QMT_CHECK(identifier == QStringLiteral("width"));
_diagram_scene_model->getDiagramSceneController()->alignWidth(_object, _diagram_scene_model->getSelectedElements(),
getMinimumSize(_diagram_scene_model->getSelectedItems()), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_HEIGHT:
QMT_CHECK(identifier == QStringLiteral("height"));
_diagram_scene_model->getDiagramSceneController()->alignHeight(_object, _diagram_scene_model->getSelectedElements(),
getMinimumSize(_diagram_scene_model->getSelectedItems()), _diagram_scene_model->getDiagram());
break;
case IAlignable::ALIGN_SIZE:
QMT_CHECK(identifier == QStringLiteral("size"));
_diagram_scene_model->getDiagramSceneController()->alignSize(_object, _diagram_scene_model->getSelectedElements(),
getMinimumSize(_diagram_scene_model->getSelectedItems()), _diagram_scene_model->getDiagram());
break;
}
}
void ObjectItem::updateStereotypeIconDisplay()
{
StereotypeDisplayVisitor stereotype_display_visitor;
stereotype_display_visitor.setModelController(_diagram_scene_model->getDiagramSceneController()->getModelController());
stereotype_display_visitor.setStereotypeController(_diagram_scene_model->getStereotypeController());
_object->accept(&stereotype_display_visitor);
_stereotype_icon_id = stereotype_display_visitor.getStereotypeIconId();
_shape_icon_id = stereotype_display_visitor.getShapeIconId();
_stereotype_icon_display = stereotype_display_visitor.getStereotypeIconDisplay();
}
void ObjectItem::updateStereotypes(const QString &stereotype_icon_id, StereotypeIcon::Display stereotype_display, const Style *style)
{
QList<QString> stereotypes = _object->getStereotypes();
if (!stereotype_icon_id.isEmpty()
&& (stereotype_display == StereotypeIcon::DISPLAY_DECORATION || stereotype_display == StereotypeIcon::DISPLAY_ICON)) {
stereotypes = _diagram_scene_model->getStereotypeController()->filterStereotypesByIconId(stereotype_icon_id, stereotypes);
}
if (!stereotype_icon_id.isEmpty() && stereotype_display == StereotypeIcon::DISPLAY_DECORATION) {
if (!_stereotype_icon) {
_stereotype_icon = new CustomIconItem(_diagram_scene_model, this);
}
_stereotype_icon->setStereotypeIconId(stereotype_icon_id);
_stereotype_icon->setBaseSize(QSizeF(_stereotype_icon->getShapeWidth(), _stereotype_icon->getShapeHeight()));
_stereotype_icon->setBrush(style->getFillBrush());
_stereotype_icon->setPen(style->getInnerLinePen());
} else if (_stereotype_icon) {
_stereotype_icon->scene()->removeItem(_stereotype_icon);
delete _stereotype_icon;
_stereotype_icon = 0;
}
if (stereotype_display != StereotypeIcon::DISPLAY_NONE && !stereotypes.isEmpty()) {
if (!_stereotypes) {
_stereotypes = new StereotypesItem(this);
}
_stereotypes->setFont(style->getSmallFont());
_stereotypes->setBrush(style->getTextBrush());
_stereotypes->setStereotypes(stereotypes);
} else if (_stereotypes) {
_stereotypes->scene()->removeItem(_stereotypes);
delete _stereotypes;
_stereotypes = 0;
}
}
QSizeF ObjectItem::getStereotypeIconMinimumSize(const StereotypeIcon &stereotype_icon, qreal minimum_width, qreal minimum_height) const
{
Q_UNUSED(minimum_width);
qreal width = 0.0;
qreal height = 0.0;
if (stereotype_icon.hasMinWidth() && !stereotype_icon.hasMinHeight()) {
width = stereotype_icon.getMinWidth();
if (stereotype_icon.getSizeLock() == StereotypeIcon::LOCK_HEIGHT || stereotype_icon.getSizeLock() == StereotypeIcon::LOCK_SIZE) {
height = stereotype_icon.getMinHeight();
} else {
height = width * stereotype_icon.getHeight() / stereotype_icon.getWidth();
}
} else if (!stereotype_icon.hasMinWidth() && stereotype_icon.hasMinHeight()) {
height = stereotype_icon.getMinHeight();
if (stereotype_icon.getSizeLock() == StereotypeIcon::LOCK_WIDTH || stereotype_icon.getSizeLock() == StereotypeIcon::LOCK_SIZE) {
width = stereotype_icon.getMinWidth();
} else {
width = height * stereotype_icon.getWidth() / stereotype_icon.getHeight();
}
} else if (stereotype_icon.hasMinWidth() && stereotype_icon.hasMinHeight()) {
if (stereotype_icon.getSizeLock() == StereotypeIcon::LOCK_RATIO) {
width = stereotype_icon.getMinWidth();
height = width * stereotype_icon.getHeight() / stereotype_icon.getWidth();
if (height < stereotype_icon.getMinHeight()) {
height = stereotype_icon.getMinHeight();
width = height * stereotype_icon.getWidth() / stereotype_icon.getHeight();
QMT_CHECK(width <= stereotype_icon.getMinWidth());
}
} else {
width = stereotype_icon.getMinWidth();
height = stereotype_icon.getMinHeight();
}
} else {
height = minimum_height;
width = height * stereotype_icon.getWidth() / stereotype_icon.getHeight();
}
return QSizeF(width, height);
}
void ObjectItem::updateDepth()
{
setZValue(_object->getDepth());
}
void ObjectItem::updateSelectionMarker(CustomIconItem *custom_icon_item)
{
if (custom_icon_item) {
StereotypeIcon stereotype_icon = custom_icon_item->getStereotypeIcon();
ResizeFlags resize_flags = RESIZE_UNLOCKED;
switch (stereotype_icon.getSizeLock()) {
case StereotypeIcon::LOCK_NONE:
resize_flags = RESIZE_UNLOCKED;
break;
case StereotypeIcon::LOCK_WIDTH:
resize_flags = RESIZE_LOCKED_WIDTH;
break;
case StereotypeIcon::LOCK_HEIGHT:
resize_flags = RESIZE_LOCKED_HEIGHT;
break;
case StereotypeIcon::LOCK_SIZE:
resize_flags = RESIZE_LOCKED_SIZE;
break;
case StereotypeIcon::LOCK_RATIO:
resize_flags = RESIZE_LOCKED_RATIO;
break;
}
updateSelectionMarker(resize_flags);
} else {
updateSelectionMarker(RESIZE_UNLOCKED);
}
}
void ObjectItem::updateSelectionMarker(ResizeFlags resize_flags)
{
if ((isSelected() || isSecondarySelected()) && resize_flags != RESIZE_LOCKED_SIZE) {
if (!_selection_marker) {
_selection_marker = new RectangularSelectionItem(this, this);
}
switch (resize_flags) {
case RESIZE_UNLOCKED:
_selection_marker->setFreedom(RectangularSelectionItem::FREEDOM_ANY);
break;
case RESIZE_LOCKED_SIZE:
QMT_CHECK(false);
break;
case RESIZE_LOCKED_WIDTH:
_selection_marker->setFreedom(RectangularSelectionItem::FREEDOM_VERTICAL_ONLY);
break;
case RESIZE_LOCKED_HEIGHT:
_selection_marker->setFreedom(RectangularSelectionItem::FREEDOM_HORIZONTAL_ONLY);
break;
case RESIZE_LOCKED_RATIO:
_selection_marker->setFreedom(RectangularSelectionItem::FREEDOM_KEEP_RATIO);
break;
}
_selection_marker->setSecondarySelected(isSelected() ? false : isSecondarySelected());
_selection_marker->setZValue(SELECTION_MARKER_ZVALUE);
} else if (_selection_marker) {
if (_selection_marker->scene()) {
_selection_marker->scene()->removeItem(_selection_marker);
}
delete _selection_marker;
_selection_marker = 0;
}
}
void ObjectItem::updateSelectionMarkerGeometry(const QRectF &object_rect)
{
if (_selection_marker) {
_selection_marker->setRect(object_rect);
}
}
void ObjectItem::updateAlignmentButtons()
{
if (isFocusSelected() && _diagram_scene_model->hasMultiObjectsSelection()) {
if (!_horizontal_align_buttons && scene()) {
_horizontal_align_buttons = new AlignButtonsItem(this, 0);
_horizontal_align_buttons->setZValue(ALIGN_BUTTONS_ZVALUE);
scene()->addItem(_horizontal_align_buttons);
}
if (!_vertical_align_buttons && scene()) {
_vertical_align_buttons = new AlignButtonsItem(this, 0);
_vertical_align_buttons->setZValue(ALIGN_BUTTONS_ZVALUE);
scene()->addItem(_vertical_align_buttons);
}
} else {
if (_horizontal_align_buttons) {
if (_horizontal_align_buttons->scene()) {
_horizontal_align_buttons->scene()->removeItem(_horizontal_align_buttons);
}
delete _horizontal_align_buttons;
_horizontal_align_buttons = 0;
}
if (_vertical_align_buttons) {
if (_vertical_align_buttons->scene()) {
_vertical_align_buttons->scene()->removeItem(_vertical_align_buttons);
}
delete _vertical_align_buttons;
_vertical_align_buttons = 0;
}
}
}
void ObjectItem::updateAlignmentButtonsGeometry(const QRectF &object_rect)
{
if (_horizontal_align_buttons) {
_horizontal_align_buttons->clear();
_horizontal_align_buttons->setPos(mapToScene(QPointF(0.0, object_rect.top() - AlignButtonsItem::NORMAL_BUTTON_HEIGHT - AlignButtonsItem::VERTICAL_DISTANCE_TO_OBEJCT)));
foreach (const ILatchable::Latch &latch, getHorizontalLatches(ILatchable::MOVE, true)) {
_horizontal_align_buttons->addButton(translateLatchTypeToAlignType(latch._latch_type), latch._identifier, mapFromScene(QPointF(latch._pos, 0.0)).x());
}
}
if (_vertical_align_buttons) {
_vertical_align_buttons->clear();
_vertical_align_buttons->setPos(mapToScene(QPointF(object_rect.left() - AlignButtonsItem::NORMAL_BUTTON_WIDTH - AlignButtonsItem::HORIZONTAL_DISTANCE_TO_OBJECT, 0.0)));
foreach (const ILatchable::Latch &latch, getVerticalLatches(ILatchable::MOVE, true)) {
_vertical_align_buttons->addButton(translateLatchTypeToAlignType(latch._latch_type), latch._identifier, mapFromScene(QPointF(0.0, latch._pos)).y());
}
}
}
IAlignable::AlignType ObjectItem::translateLatchTypeToAlignType(ILatchable::LatchType latch_type)
{
IAlignable::AlignType align_type = IAlignable::ALIGN_LEFT;
switch (latch_type) {
case ILatchable::LEFT:
align_type = IAlignable::ALIGN_LEFT;
break;
case ILatchable::TOP:
align_type = IAlignable::ALIGN_TOP;
break;
case ILatchable::RIGHT:
align_type = IAlignable::ALIGN_RIGHT;
break;
case ILatchable::BOTTOM:
align_type = IAlignable::ALIGN_BOTTOM;
break;
case ILatchable::HCENTER:
align_type = IAlignable::ALIGN_HCENTER;
break;
case ILatchable::VCENTER:
align_type = IAlignable::ALIGN_VCENTER;
break;
case ILatchable::NONE:
QMT_CHECK(false);
break;
}
return align_type;
}
const Style *ObjectItem::getAdaptedStyle(const QString &stereotype_icon_id)
{
QList<const DObject *> colliding_objects;
foreach (const QGraphicsItem *item, _diagram_scene_model->collectCollidingObjectItems(this, DiagramSceneModel::COLLIDING_ITEMS)) {
if (const ObjectItem *object_item = dynamic_cast<const ObjectItem *>(item)) {
colliding_objects.append(object_item->getObject());
}
}
QColor base_color;
if (!stereotype_icon_id.isEmpty()) {
StereotypeIcon stereotype_icon = _diagram_scene_model->getStereotypeController()->findStereotypeIcon(stereotype_icon_id);
base_color = stereotype_icon.getBaseColor();
}
return _diagram_scene_model->getStyleController()->adaptObjectStyle(
StyledObject(getObject(),
ObjectVisuals(
getObject()->getVisualPrimaryRole(),
getObject()->getVisualSecondaryRole(),
getObject()->isVisualEmphasized(),
base_color,
getObject()->getDepth()),
colliding_objects));
}
bool ObjectItem::showContext() const
{
bool showContext = !_object->getContext().isEmpty();
if (showContext) {
// TODO Because of this algorithm adding, moving, removing of one item need to update() all colliding items as well
QMT_CHECK(getObject()->getModelUid().isValid());
MObject *mobject = _diagram_scene_model->getDiagramController()->getModelController()->findObject(getObject()->getModelUid());
QMT_CHECK(mobject);
MObject *owner = mobject->getOwner();
if (owner) {
foreach (QGraphicsItem *item, _diagram_scene_model->collectCollidingObjectItems(this, DiagramSceneModel::COLLIDING_OUTER_ITEMS)) {
if (ObjectItem *object_item = dynamic_cast<ObjectItem *>(item)) {
if (object_item->getObject()->getModelUid().isValid() && object_item->getObject()->getModelUid() == owner->getUid()) {
showContext = false;
break;
}
}
}
}
}
return showContext;
}
bool ObjectItem::extendContextMenu(QMenu *menu)
{
Q_UNUSED(menu);
return false;
}
bool ObjectItem::handleSelectedContextMenuAction(QAction *action)
{
Q_UNUSED(action);
return false;
}
void ObjectItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) {
_diagram_scene_model->selectItem(this, event->modifiers() & Qt::ControlModifier);
}
if (event->button() == Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, QPointF(0.0, 0.0));
}
}
void ObjectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, event->scenePos() - event->lastScenePos());
}
}
void ObjectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
_diagram_scene_model->moveSelectedItems(this, event->scenePos() - event->lastScenePos());
if (event->scenePos() != event->buttonDownScenePos(Qt::LeftButton)) {
_diagram_scene_model->alignSelectedItemsPositionOnRaster();
}
}
}
void ObjectItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
_diagram_scene_model->onDoubleClickedItem(this);
}
}
void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
QMenu menu;
bool add_separator = false;
if (getDiagramSceneModel()->getDiagramSceneController()->getElementTasks()->hasDiagram(_object, _diagram_scene_model->getDiagram())) {
menu.addAction(new ContextMenuAction(QObject::tr("Open Diagram"), QStringLiteral("openDiagram"), &menu));
add_separator = true;
} else if (getDiagramSceneModel()->getDiagramSceneController()->getElementTasks()->mayCreateDiagram(_object, _diagram_scene_model->getDiagram())) {
menu.addAction(new ContextMenuAction(QObject::tr("Create Diagram"), QStringLiteral("createDiagram"), &menu));
add_separator = true;
}
if (extendContextMenu(&menu)) {
add_separator = true;
}
if (add_separator) {
menu.addSeparator();
}
menu.addAction(new ContextMenuAction(QObject::tr("Remove"), QStringLiteral("remove"), QKeySequence(QKeySequence::Delete), &menu));
menu.addAction(new ContextMenuAction(QObject::tr("Delete"), QStringLiteral("delete"), QKeySequence(Qt::CTRL + Qt::Key_D), &menu));
//menu.addAction(new ContextMenuAction(QObject::tr("Select in Model Tree"), QStringLiteral("selectInModelTree"), &menu));
QMenu align_menu;
align_menu.setTitle(QObject::tr("Align Objects"));
align_menu.addAction(new ContextMenuAction(QObject::tr("Align Left"), QStringLiteral("alignLeft"), &align_menu));
align_menu.addAction(new ContextMenuAction(QObject::tr("Center Vertically"), QStringLiteral("centerVertically"), &align_menu));
align_menu.addAction(new ContextMenuAction(QObject::tr("Align Right"), QStringLiteral("alignRight"), &align_menu));
align_menu.addSeparator();
align_menu.addAction(new ContextMenuAction(QObject::tr("Align Top"), QStringLiteral("alignTop"), &align_menu));
align_menu.addAction(new ContextMenuAction(QObject::tr("Center Horizontally"), QStringLiteral("centerHorizontally"), &align_menu));
align_menu.addAction(new ContextMenuAction(QObject::tr("Align Bottom"), QStringLiteral("alignBottom"), &align_menu));
align_menu.addSeparator();
align_menu.addAction(new ContextMenuAction(QObject::tr("Same Width"), QStringLiteral("sameWidth"), &align_menu));
align_menu.addAction(new ContextMenuAction(QObject::tr("Same Height"), QStringLiteral("sameHeight"), &align_menu));
align_menu.addAction(new ContextMenuAction(QObject::tr("Same Size"), QStringLiteral("sameSize"), &align_menu));
align_menu.setEnabled(_diagram_scene_model->hasMultiObjectsSelection());
menu.addMenu(&align_menu);
QAction *selected_action = menu.exec(event->screenPos());
if (selected_action) {
if (!handleSelectedContextMenuAction(selected_action)) {
ContextMenuAction *action = dynamic_cast<ContextMenuAction *>(selected_action);
QMT_CHECK(action);
if (action->getId() == QStringLiteral("openDiagram")) {
_diagram_scene_model->getDiagramSceneController()->getElementTasks()->openDiagram(_object, _diagram_scene_model->getDiagram());
} else if (action->getId() == QStringLiteral("createDiagram")) {
_diagram_scene_model->getDiagramSceneController()->getElementTasks()->createAndOpenDiagram(_object, _diagram_scene_model->getDiagram());
} else if (action->getId() == QStringLiteral("remove")) {
DSelection selection = _diagram_scene_model->getSelectedElements();
if (selection.isEmpty()) {
selection.append(_object->getUid(), _diagram_scene_model->getDiagram()->getUid());
}
_diagram_scene_model->getDiagramController()->deleteElements(selection, _diagram_scene_model->getDiagram());
} else if (action->getId() == QStringLiteral("delete")) {
DSelection selection = _diagram_scene_model->getSelectedElements();
if (selection.isEmpty()) {
selection.append(_object->getUid(), _diagram_scene_model->getDiagram()->getUid());
}
_diagram_scene_model->getDiagramSceneController()->deleteFromDiagram(selection, _diagram_scene_model->getDiagram());
} else if (action->getId() == QStringLiteral("selectInModelTree")) {
// TODO implement
} else if (action->getId() == QStringLiteral("alignLeft")) {
align(IAlignable::ALIGN_LEFT, QStringLiteral("left"));
} else if (action->getId() == QStringLiteral("centerVertically")) {
align(IAlignable::ALIGN_VCENTER, QStringLiteral("center"));
} else if (action->getId() == QStringLiteral("alignRight")) {
align(IAlignable::ALIGN_RIGHT, QStringLiteral("right"));
} else if (action->getId() == QStringLiteral("alignTop")) {
align(IAlignable::ALIGN_TOP, QStringLiteral("top"));
} else if (action->getId() == QStringLiteral("centerHorizontally")) {
align(IAlignable::ALIGN_HCENTER, QStringLiteral("center"));
} else if (action->getId() == QStringLiteral("alignBottom")) {
align(IAlignable::ALIGN_BOTTOM, QStringLiteral("bottom"));
} else if (action->getId() == QStringLiteral("sameWidth")) {
align(IAlignable::ALIGN_WIDTH, QStringLiteral("width"));
} else if (action->getId() == QStringLiteral("sameHeight")) {
align(IAlignable::ALIGN_HEIGHT, QStringLiteral("height"));
} else if (action->getId() == QStringLiteral("sameSize")) {
align(IAlignable::ALIGN_SIZE, QStringLiteral("size"));
}
}
}
}
QSizeF ObjectItem::getMinimumSize(const QSet<QGraphicsItem *> &items) const
{
QSizeF minimum_size(0.0, 0.0);
foreach (QGraphicsItem *item, items) {
if (IResizable *resizable = dynamic_cast<IResizable *>(item)) {
QSizeF size = resizable->getMinimumSize();
if (size.width() > minimum_size.width()) {
minimum_size.setWidth(size.width());
}
if (size.height() > minimum_size.height()) {
minimum_size.setHeight(size.height());
}
}
}
return minimum_size;
}
}

View File

@@ -0,0 +1,235 @@
/***************************************************************************
**
** 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 QMT_OBJECTITEM_H
#define QMT_OBJECTITEM_H
#include <QGraphicsItem>
#include "qmt/diagram_scene/capabilities/intersectionable.h"
#include "qmt/diagram_scene/capabilities/resizable.h"
#include "qmt/diagram_scene/capabilities/moveable.h"
#include "qmt/diagram_scene/capabilities/selectable.h"
#include "qmt/diagram_scene/capabilities/latchable.h"
#include "qmt/diagram_scene/capabilities/alignable.h"
#include "qmt/stereotype/stereotypeicon.h"
QT_BEGIN_NAMESPACE
class QAction;
QT_END_NAMESPACE
namespace qmt {
class DObject;
class DiagramSceneModel;
class StereotypesItem;
class CustomIconItem;
class RectangularSelectionItem;
class AlignButtonsItem;
class Style;
// typical z-values for graphic items
static const int SHAPE_ZVALUE = -100; // the filled background of the shape
static const int SHAPE_DETAILS_ZVALUE = -90; // any details to the shape (e.g. extra lines in shape)
static const int SELECTION_MARKER_ZVALUE = 100;
class ObjectItem :
public QGraphicsItem,
public IIntersectionable,
public IResizable,
public IMoveable,
public ISelectable,
public ILatchable,
public IAlignable
{
protected:
enum ResizeFlags {
RESIZE_UNLOCKED,
RESIZE_LOCKED_SIZE,
RESIZE_LOCKED_WIDTH,
RESIZE_LOCKED_HEIGHT,
RESIZE_LOCKED_RATIO
};
public:
ObjectItem(DObject *object, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent = 0);
~ObjectItem();
public:
DObject *getObject() const { return _object; }
DiagramSceneModel *getDiagramSceneModel() const { return _diagram_scene_model; }
public:
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
public:
virtual void update() = 0;
public:
bool intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const = 0;
public:
QPointF getPos() const;
QRectF getRect() const;
QSizeF getMinimumSize() const = 0;
void setPosAndRect(const QPointF &original_pos, const QRectF &original_rect, const QPointF &top_left_delta, const QPointF &bottom_right_delta);
void alignItemSizeToRaster(Side adjust_horizontal_side, Side adjust_vertical_side, double raster_width, double raster_height);
public:
void moveDelta(const QPointF &delta);
void alignItemPositionToRaster(double raster_width, double raster_height);
public:
bool isSecondarySelected() const;
void setSecondarySelected(bool secondary_selected);
bool isFocusSelected() const;
void setFocusSelected(bool focus_selected);
public:
QList<Latch> getHorizontalLatches(Action action, bool grabbed_item) const;
QList<Latch> getVerticalLatches(Action action, bool grabbed_item) const;
public:
void align(AlignType align_type, const QString &identifier);
protected:
void updateStereotypeIconDisplay();
QString getStereotypeIconId() const { return _stereotype_icon_id; }
QString getShapeIconId() const { return _shape_icon_id; }
StereotypeIcon::Display getStereotypeIconDisplay() const { return _stereotype_icon_display; }
void updateStereotypes(const QString &stereotype_icon_id, StereotypeIcon::Display stereotype_display, const Style *style);
StereotypesItem *getStereotypesItem() const { return _stereotypes; }
CustomIconItem *getStereotypeIconItem() const { return _stereotype_icon; }
QSizeF getStereotypeIconMinimumSize(const StereotypeIcon &stereotype_icon, qreal minimum_width, qreal minimum_height) const;
void updateDepth();
void updateSelectionMarker(CustomIconItem *custom_icon_item);
void updateSelectionMarker(ResizeFlags resize_flags);
void updateSelectionMarkerGeometry(const QRectF &object_rect);
void updateAlignmentButtons();
void updateAlignmentButtonsGeometry(const QRectF &object_rect);
IAlignable::AlignType translateLatchTypeToAlignType(ILatchable::LatchType latch_type);
const Style *getAdaptedStyle(const QString &stereotype_icon_id);
bool showContext() const;
virtual bool extendContextMenu(QMenu *menu);
virtual bool handleSelectedContextMenuAction(QAction *action);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
private:
QSizeF getMinimumSize(const QSet<QGraphicsItem *> &items) const;
private:
DObject *_object;
DiagramSceneModel *_diagram_scene_model;
bool _secondary_selected;
bool _focus_selected;
QString _stereotype_icon_id;
QString _shape_icon_id;
StereotypeIcon::Display _stereotype_icon_display;
StereotypesItem *_stereotypes;
CustomIconItem *_stereotype_icon;
RectangularSelectionItem *_selection_marker;
AlignButtonsItem *_horizontal_align_buttons;
AlignButtonsItem *_vertical_align_buttons;
};
}
#endif // QMT_OBJECTITEM_H

View File

@@ -0,0 +1,399 @@
/***************************************************************************
**
** 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 "packageitem.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram/dpackage.h"
#include "qmt/diagram_scene/diagramsceneconstants.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/contextlabelitem.h"
#include "qmt/diagram_scene/parts/customiconitem.h"
#include "qmt/diagram_scene/parts/relationstarter.h"
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/stereotype/stereotypeicon.h"
#include "qmt/style/style.h"
#include "qmt/tasks/diagramscenecontroller.h"
#include <QGraphicsScene>
#include <QBrush>
#include <QPen>
#include <QFont>
#include <algorithm>
namespace qmt {
static const qreal TAB_HORIZ_BORDER = 4.0;
static const qreal TAB_VERT_BORDER = 4.0;
static const qreal TAB_MIN_RIGHT_SPACE = 16.0;
static const qreal BODY_VERT_BORDER = 4.0;
static const qreal BODY_HORIZ_BORDER = 4.0;
static const qreal BODY_MIN_HEIGHT = 24.0;
static const qreal MINIMUM_AUTO_WIDTH = 100.0;
static const qreal MINIMUM_AUTO_HEIGHT = 70.0;
struct PackageItem::ShapeGeometry {
ShapeGeometry(const QSizeF &minimum_size, const QSizeF &minimum_tab_size)
: _minimum_size(minimum_size),
_minimum_tab_size(minimum_tab_size)
{
}
QSizeF _minimum_size;
QSizeF _minimum_tab_size;
};
PackageItem::PackageItem(DPackage *package, DiagramSceneModel *diagram_scene_model, QGraphicsItem *parent)
: ObjectItem(package, diagram_scene_model, parent),
_custom_icon(0),
_shape(0),
_package_name(0),
_context_label(0),
_relation_starter(0)
{
}
PackageItem::~PackageItem()
{
}
void PackageItem::update()
{
prepareGeometryChange();
updateStereotypeIconDisplay();
const Style *style = getAdaptedStyle(getStereotypeIconId());
// custom icon
if (getStereotypeIconDisplay() == StereotypeIcon::DISPLAY_ICON) {
if (!_custom_icon) {
_custom_icon = new CustomIconItem(getDiagramSceneModel(), this);
}
_custom_icon->setStereotypeIconId(getStereotypeIconId());
_custom_icon->setBaseSize(getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT));
_custom_icon->setBrush(style->getFillBrush());
_custom_icon->setPen(style->getOuterLinePen());
_custom_icon->setZValue(SHAPE_ZVALUE);
} else if (_custom_icon) {
_custom_icon->scene()->removeItem(_custom_icon);
delete _custom_icon;
_custom_icon = 0;
}
// shape
if (!_custom_icon) {
if (!_shape) {
_shape = new QGraphicsPolygonItem(this);
}
_shape->setBrush(style->getFillBrush());
_shape->setPen(style->getOuterLinePen());
_shape->setZValue(SHAPE_ZVALUE);
} else if (_shape) {
_shape->scene()->removeItem(_shape);
delete _shape;
_shape = 0;
}
// stereotypes
updateStereotypes(getStereotypeIconId(), getStereotypeIconDisplay(), style);
// package name
if (!_package_name) {
_package_name = new QGraphicsSimpleTextItem(this);
}
_package_name->setBrush(style->getTextBrush());
_package_name->setFont(style->getHeaderFont());
_package_name->setText(getObject()->getName());
// context
if (showContext()) {
if (!_context_label) {
_context_label = new ContextLabelItem(this);
}
_context_label->setFont(style->getSmallFont());
_context_label->setBrush(style->getTextBrush());
_context_label->setContext(getObject()->getContext());
} else if (_context_label) {
_context_label->scene()->removeItem(_context_label);
delete _context_label;
_context_label = 0;
}
updateSelectionMarker(_custom_icon);
// relation starters
if (isFocusSelected()) {
if (!_relation_starter) {
_relation_starter = new RelationStarter(this, getDiagramSceneModel(), 0);
scene()->addItem(_relation_starter);
_relation_starter->setZValue(RELATION_STARTER_ZVALUE);
_relation_starter->addArrow(QStringLiteral("dependency"), ArrowItem::SHAFT_DASHED, ArrowItem::HEAD_OPEN);
}
} else if (_relation_starter) {
scene()->removeItem(_relation_starter);
delete _relation_starter;
_relation_starter = 0;
}
updateAlignmentButtons();
updateGeometry();
}
bool PackageItem::intersectShapeWithLine(const QLineF &line, QPointF *intersection_point, QLineF *intersection_line) const
{
QPolygonF polygon;
if (_custom_icon) {
// TODO use custom_icon path as shape
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
} else {
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
ShapeGeometry shape = calcMinimumGeometry();
polygon << rect.topLeft() << (rect.topLeft() + QPointF(shape._minimum_tab_size.width(), 0.0))
<< (rect.topLeft() + QPointF(shape._minimum_tab_size.width(), shape._minimum_tab_size.height()))
<< rect.topRight() + QPointF(0.0, shape._minimum_tab_size.height())
<< rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
}
return GeometryUtilities::intersect(polygon, line, intersection_point, intersection_line);
}
QSizeF PackageItem::getMinimumSize() const
{
ShapeGeometry geometry = calcMinimumGeometry();
return geometry._minimum_size;
}
QList<ILatchable::Latch> PackageItem::getHorizontalLatches(ILatchable::Action action, bool grabbed_item) const
{
return ObjectItem::getHorizontalLatches(action, grabbed_item);
}
QList<ILatchable::Latch> PackageItem::getVerticalLatches(ILatchable::Action action, bool grabbed_item) const
{
return ObjectItem::getVerticalLatches(action, grabbed_item);
}
#if 0
QList<qreal> PackageItem::getHorizontalLatches() const
{
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
return QList<qreal>() << rect.left() << rect.center().x() << rect.right();
}
QList<qreal> PackageItem::getVerticalLatches() const
{
QRectF rect = getObject()->getRect();
rect.translate(getObject()->getPos());
ShapeGeometry shape = calcMinimumGeometry();
return QList<qreal>() << rect.topLeft().y() << (rect.topLeft() + QPointF(0.0, shape._minimum_tab_size.height())).y() << rect.center().y() << rect.bottomRight().y();
}
#endif
QPointF PackageItem::getRelationStartPos() const
{
return pos();
}
void PackageItem::relationDrawn(const QString &id, const QPointF &to_scene_pos, const QList<QPointF> &intermediate_points)
{
DElement *target_element = getDiagramSceneModel()->findTopmostElement(to_scene_pos);
if (target_element) {
if (id == QStringLiteral("dependency")) {
DObject *dependant_object = dynamic_cast<DObject *>(target_element);
if (dependant_object) {
getDiagramSceneModel()->getDiagramSceneController()->createDependency(getObject(), dependant_object, intermediate_points, getDiagramSceneModel()->getDiagram());
}
}
}
}
PackageItem::ShapeGeometry PackageItem::calcMinimumGeometry() const
{
double width = 0.0;
double height = 0.0;
double tab_height = 0.0;
double tab_width = 0.0;
if (_custom_icon) {
return ShapeGeometry(getStereotypeIconMinimumSize(_custom_icon->getStereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT), QSizeF(tab_width, tab_height));
}
double body_height = 0.0;
double body_width = 0.0;
tab_height += TAB_VERT_BORDER;
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
tab_width = std::max(tab_width, stereotypes_item->boundingRect().width() + 2 * TAB_HORIZ_BORDER);
tab_height += stereotypes_item->boundingRect().height();
}
if (_package_name) {
tab_width = std::max(tab_width, _package_name->boundingRect().width() + 2 * TAB_HORIZ_BORDER);
tab_height += _package_name->boundingRect().height();
}
tab_height += TAB_VERT_BORDER;
width = std::max(width, tab_width + TAB_MIN_RIGHT_SPACE);
height += tab_height;
body_height = BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
body_width = std::max(body_width, stereotype_icon_item->boundingRect().width() + 2 * BODY_HORIZ_BORDER);
body_height += stereotype_icon_item->boundingRect().height();
}
if (_context_label) {
body_height += _context_label->getHeight();
}
body_height += BODY_VERT_BORDER;
body_height = std::max(body_height, BODY_MIN_HEIGHT);
width = std::max(width, body_width);
height += body_height;
return ShapeGeometry(GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT), QSizeF(tab_width, tab_height));
}
void PackageItem::updateGeometry()
{
prepareGeometryChange();
ShapeGeometry geometry = calcMinimumGeometry();
double width = geometry._minimum_size.width();
double height = geometry._minimum_size.height();
double tab_width = geometry._minimum_tab_size.width();
double tab_height = geometry._minimum_tab_size.height();
// calc width and height
if (getObject()->hasAutoSize()) {
if (!_custom_icon) {
if (width < MINIMUM_AUTO_WIDTH) {
width = MINIMUM_AUTO_WIDTH;
}
if (height < MINIMUM_AUTO_HEIGHT) {
height = MINIMUM_AUTO_HEIGHT;
}
}
} else {
QRectF rect = getObject()->getRect();
if (rect.width() > width) {
width = rect.width();
}
if (rect.height() > height) {
height = rect.height();
}
}
// update sizes and positions
double left = -width / 2.0;
double right = width / 2.0;
double top = -height / 2.0;
double y = top;
setPos(getObject()->getPos());
QRectF rect(left, top, width, height);
// the object is updated without calling DiagramController intentionally.
// attribute rect is not a real attribute stored on DObject but
// a backup for the graphics item used for manual resized and persistency.
getObject()->setRect(rect);
if (_custom_icon) {
_custom_icon->setPos(left, top);
_custom_icon->setActualSize(QSizeF(width, height));
y += height;
y += BODY_VERT_BORDER;
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
stereotypes_item->setPos(-stereotypes_item->boundingRect().width() / 2.0, y);
y += stereotypes_item->boundingRect().height();
}
if (_package_name) {
_package_name->setPos(-_package_name->boundingRect().width() / 2.0, y);
y += _package_name->boundingRect().height();
}
if (_context_label) {
_context_label->resetMaxWidth();
_context_label->setPos(-_context_label->boundingRect().width() / 2.0, y);
y += _context_label->boundingRect().height();
}
} else if (_shape) {
QPolygonF polygon;
polygon << rect.topLeft()
<< QPointF(left + tab_width, top)
<< QPointF(left + tab_width, top + tab_height)
<< QPointF(right, top + tab_height)
<< rect.bottomRight()
<< rect.bottomLeft();
_shape->setPolygon(polygon);
y += TAB_VERT_BORDER;
if (StereotypesItem *stereotypes_item = getStereotypesItem()) {
stereotypes_item->setPos(left + TAB_HORIZ_BORDER, y);
y += stereotypes_item->boundingRect().height();
}
if (_package_name) {
_package_name->setPos(left + TAB_HORIZ_BORDER, y);
y += _package_name->boundingRect().height();
}
y += TAB_VERT_BORDER;
y += BODY_VERT_BORDER;
if (CustomIconItem *stereotype_icon_item = getStereotypeIconItem()) {
stereotype_icon_item->setPos(right - stereotype_icon_item->boundingRect().width() - BODY_HORIZ_BORDER, y);
y += stereotype_icon_item->boundingRect().height();
}
if (_context_label) {
_context_label->setMaxWidth(width - 2 * BODY_HORIZ_BORDER);
_context_label->setPos(-_context_label->boundingRect().width() / 2.0, y);
y += _context_label->boundingRect().height();
}
}
updateSelectionMarkerGeometry(rect);
if (_relation_starter) {
_relation_starter->setPos(mapToScene(QPointF(right + 8.0, top)));
}
updateAlignmentButtonsGeometry(rect);
updateDepth();
}
}

Some files were not shown because too many files have changed in this diff Show More