forked from qt-creator/qt-creator
ScxmlEditor: Initial import
Change-Id: I4701b77ebd4e2520f2616c42206ac17be3a12b60 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
90
src/plugins/scxmleditor/plugin_interface/actionhandler.cpp
Normal file
90
src/plugins/scxmleditor/plugin_interface/actionhandler.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "actionhandler.h"
|
||||
#include "mytypes.h"
|
||||
|
||||
#include <QAction>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ActionHandler::ActionHandler(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
using AH = ActionHandler;
|
||||
|
||||
const struct {
|
||||
const char *icon;
|
||||
QString name;
|
||||
QString tooltip;
|
||||
const char *keyseq;
|
||||
bool checkable;
|
||||
} actionInfos[] = {
|
||||
{ ":/scxmleditor/images/icon-zoom-in.png", AH::tr("Zoom In"), AH::tr("Zoom In (Ctrl + + / Ctrl + Wheel)"), "Ctrl++", false },
|
||||
{ ":/scxmleditor/images/icon-zoom-out.png", AH::tr("Zoom Out"), AH::tr("Zoom Out (Ctrl + - / Ctrl + Wheel)"), "Ctrl+-", false },
|
||||
{ ":/scxmleditor/images/icon-fit-screen.png", AH::tr("Fit to View"), AH::tr("Fit to View (F11)"), "F11", false },
|
||||
{ ":/scxmleditor/images/icon-pan.png", AH::tr("Panning"), AH::tr("Panning (Shift)"), "Shift", true },
|
||||
|
||||
{ ":/scxmleditor/images/icon-search.png", AH::tr("Magnifier"), AH::tr("Magnifier Tool (Alt)"), "Alt", true },
|
||||
{ ":/scxmleditor/images/navigator.png", AH::tr("Navigator"), AH::tr("Navigator (Ctrl+E)"), "Ctrl+E", true },
|
||||
|
||||
{ ":/scxmleditor/images/icon-copy.png", AH::tr("Copy"), AH::tr("Copy (Ctrl + C)"), "Ctrl+C", false },
|
||||
{ ":/scxmleditor/images/icon-cut.png", AH::tr("Cut"), AH::tr("Cut (Ctrl + X)"), "Ctrl+X", false },
|
||||
{ ":/scxmleditor/images/icon-paste.png", AH::tr("Paste"), AH::tr("Paste (Ctrl + V)"), "Ctrl+V", false },
|
||||
{ ":/scxmleditor/images/screenshot.png", AH::tr("Screenshot"), AH::tr("Screenshot (Ctrl + Shift + C)"), "Ctrl+Shift+C", false },
|
||||
{ ":/scxmleditor/images/icon-export-canvas.png", AH::tr("Export to Image"), AH::tr("Export to Image"), "Ctrl+Shift+E", false },
|
||||
{ ":/scxmleditor/images/fullnamespace.png", AH::tr("Toggle Full Namespace"), AH::tr("Toggle Full Namespace"), "Ctrl+Shift+N", true },
|
||||
|
||||
{ ":/scxmleditor/images/align_left.png", AH::tr("Align Left"), AH::tr("Align Left (Ctrl+L,1)"), "Ctrl+L,1", false },
|
||||
{ ":/scxmleditor/images/align_right.png", AH::tr("Align Right"), AH::tr("Align Right (Ctrl+L,2)"), "Ctrl+L,2", false },
|
||||
{ ":/scxmleditor/images/align_top.png", AH::tr("Align Top"), AH::tr("Align Top (Ctrl+L,3)"), "Ctrl+L,3", false },
|
||||
{ ":/scxmleditor/images/align_bottom.png", AH::tr("Align Bottom"), AH::tr("Align Bottom (Ctrl+L,4)"), "Ctrl+L,4", false },
|
||||
{ ":/scxmleditor/images/align_horizontal.png", AH::tr("Align Horizontal"), AH::tr("Align Horizontal (Ctrl+L,5)"), "Ctrl+L,5", false },
|
||||
{ ":/scxmleditor/images/align_vertical.png", AH::tr("Align Vertical"), AH::tr("Align Vertical (Ctrl+L,6)"), "Ctrl+L,6", false },
|
||||
{ ":/scxmleditor/images/adjust_width.png", AH::tr("Adjust Width"), AH::tr("Adjust Width (Ctrl+L,7)"), "Ctrl+L,7", false },
|
||||
{ ":/scxmleditor/images/adjust_height.png", AH::tr("Adjust Height"), AH::tr("Adjust Height (Ctrl+L,8)"), "Ctrl+L,8", false },
|
||||
{ ":/scxmleditor/images/adjust_size.png", AH::tr("Adjust Size"), AH::tr("Adjust Size (Ctrl+L,9)"), "Ctrl+L,9", false },
|
||||
|
||||
{ ":/scxmleditor/images/statistics.png", AH::tr("Show Statistics..."), AH::tr("Show Statistics"), "", false }
|
||||
};
|
||||
|
||||
// Init actions
|
||||
for (auto info: actionInfos) {
|
||||
auto action = new QAction(QIcon(QLatin1String(info.icon)), info.name, this);
|
||||
action->setCheckable(info.checkable);
|
||||
action->setToolTip(info.tooltip);
|
||||
action->setShortcut(QKeySequence(QLatin1String(info.keyseq)));
|
||||
|
||||
m_actions << action;
|
||||
}
|
||||
}
|
||||
|
||||
QAction *ActionHandler::action(ActionType type) const
|
||||
{
|
||||
if (type >= ActionZoomIn && type < ActionLast)
|
||||
return m_actions[type];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
52
src/plugins/scxmleditor/plugin_interface/actionhandler.h
Normal file
52
src/plugins/scxmleditor/plugin_interface/actionhandler.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mytypes.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QAction)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ActionHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ActionHandler(QObject *parent = nullptr);
|
||||
|
||||
QAction *action(ActionType type) const;
|
||||
|
||||
private:
|
||||
QVector<QAction*> m_actions;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
52
src/plugins/scxmleditor/plugin_interface/actionprovider.h
Normal file
52
src/plugins/scxmleditor/plugin_interface/actionprovider.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QMenu)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlTag;
|
||||
|
||||
class ActionProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ActionProvider(QObject *parent = nullptr)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void initStateMenu(const ScxmlTag *tag, QMenu *menu) = 0;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "attributeitemdelegate.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
AttributeItemDelegate::AttributeItemDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
, m_tag(0)
|
||||
{
|
||||
}
|
||||
|
||||
void AttributeItemDelegate::setTag(ScxmlTag *tag)
|
||||
{
|
||||
m_tag = tag;
|
||||
}
|
||||
|
||||
ScxmlTag *AttributeItemDelegate::tag() const
|
||||
{
|
||||
return m_tag;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scxmltag.h"
|
||||
|
||||
#include <QPointer>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class AttributeItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AttributeItemDelegate(QObject *parent = nullptr);
|
||||
|
||||
void setTag(ScxmlTag *tag);
|
||||
ScxmlTag *tag() const;
|
||||
|
||||
protected:
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "attributeitemmodel.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
AttributeItemModel::AttributeItemModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void AttributeItemModel::setTag(ScxmlTag *tag)
|
||||
{
|
||||
beginResetModel();
|
||||
m_tag = tag;
|
||||
m_document = m_tag ? m_tag->document() : 0;
|
||||
endResetModel();
|
||||
emit layoutChanged();
|
||||
emit dataChanged(QModelIndex(), QModelIndex());
|
||||
}
|
||||
|
||||
ScxmlTag *AttributeItemModel::tag() const
|
||||
{
|
||||
return m_tag;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmltag.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QPointer>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class AttributeItemModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AttributeItemModel(QObject *parent = nullptr);
|
||||
|
||||
virtual void setTag(ScxmlTag *tag);
|
||||
ScxmlTag *tag() const;
|
||||
|
||||
protected:
|
||||
QPointer<ScxmlDocument> m_document;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
430
src/plugins/scxmleditor/plugin_interface/baseitem.cpp
Normal file
430
src/plugins/scxmleditor/plugin_interface/baseitem.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "baseitem.h"
|
||||
#include "actionhandler.h"
|
||||
#include "actionprovider.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "sceneutils.h"
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "scxmltagutils.h"
|
||||
#include "scxmluifactory.h"
|
||||
#include "stateitem.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QUndoStack>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
BaseItem::BaseItem(BaseItem *parent)
|
||||
: QGraphicsObject(parent)
|
||||
{
|
||||
setFlag(ItemIsFocusable, true);
|
||||
setItemBoundingRect(QRectF(-60, -50, 120, 100));
|
||||
|
||||
m_scene = static_cast<GraphicsScene*>(scene());
|
||||
if (m_scene)
|
||||
m_scene->addChild(this);
|
||||
}
|
||||
|
||||
BaseItem::~BaseItem()
|
||||
{
|
||||
if (m_scene)
|
||||
m_scene->removeChild(this);
|
||||
}
|
||||
|
||||
void BaseItem::checkParentBoundingRect()
|
||||
{
|
||||
BaseItem *parentBaseItem = this->parentBaseItem();
|
||||
if (parentBaseItem && type() >= InitialStateType && !parentBaseItem->blockUpdates()) {
|
||||
auto parentStateItem = qgraphicsitem_cast<StateItem*>(parentBaseItem);
|
||||
if (parentStateItem && (parentStateItem->type() >= StateType))
|
||||
parentStateItem->updateBoundingRect();
|
||||
}
|
||||
}
|
||||
|
||||
void BaseItem::updatePolygon()
|
||||
{
|
||||
m_polygon.clear();
|
||||
m_polygon << m_boundingRect.topLeft()
|
||||
<< m_boundingRect.topRight()
|
||||
<< m_boundingRect.bottomRight()
|
||||
<< m_boundingRect.bottomLeft()
|
||||
<< m_boundingRect.topLeft();
|
||||
}
|
||||
|
||||
void BaseItem::updateDepth()
|
||||
{
|
||||
const BaseItem *baseItem = parentBaseItem();
|
||||
m_depth = baseItem ? baseItem->depth() + 1 : 0;
|
||||
update();
|
||||
}
|
||||
|
||||
void BaseItem::setItemBoundingRect(const QRectF &r)
|
||||
{
|
||||
if (m_boundingRect != r) {
|
||||
prepareGeometryChange();
|
||||
|
||||
m_boundingRect = r;
|
||||
|
||||
if (!m_blockUpdates)
|
||||
checkParentBoundingRect();
|
||||
|
||||
updatePolygon();
|
||||
emit geometryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant BaseItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
switch (change) {
|
||||
case ItemSceneHasChanged:
|
||||
m_scene = static_cast<GraphicsScene*>(scene());
|
||||
if (m_scene)
|
||||
m_scene->addChild(this);
|
||||
break;
|
||||
case ItemSelectedHasChanged: {
|
||||
emit selectedStateChanged(value.toBool());
|
||||
if (value.toBool() && tag())
|
||||
tag()->document()->setCurrentTag(tag());
|
||||
break;
|
||||
}
|
||||
case ItemPositionChange:
|
||||
if (m_scene && type() >= InitialStateType) {
|
||||
// Snap to items
|
||||
QPointF currentCenter = sceneCenter();
|
||||
QPointF targetCenter;
|
||||
QPair<bool, bool> res = m_scene->checkSnapToItem(this, currentCenter, targetCenter);
|
||||
|
||||
QPointF val = value.toPointF();
|
||||
QPointF change = val - pos();
|
||||
if (res.first && qAbs(change.x()) < 12)
|
||||
val.setX(pos().x() + targetCenter.x() - currentCenter.x());
|
||||
if (res.second && qAbs(change.y()) < 12)
|
||||
val.setY(pos().y() + targetCenter.y() - currentCenter.y());
|
||||
|
||||
return val;
|
||||
}
|
||||
break;
|
||||
case ItemParentChange:
|
||||
case ItemPositionHasChanged:
|
||||
case ItemTransformHasChanged:
|
||||
updateUIProperties();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QGraphicsObject::itemChange(change, value);
|
||||
}
|
||||
|
||||
void BaseItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
|
||||
{
|
||||
if (e->button() == Qt::RightButton) {
|
||||
e->accept();
|
||||
showContextMenu(e);
|
||||
} else {
|
||||
QGraphicsObject::mousePressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseItem::showContextMenu(QGraphicsSceneMouseEvent *e)
|
||||
{
|
||||
checkSelectionBeforeContextMenu(e);
|
||||
QMenu menu;
|
||||
createContextMenu(&menu);
|
||||
selectedMenuAction(menu.exec(e->screenPos()));
|
||||
}
|
||||
|
||||
void BaseItem::checkSelectionBeforeContextMenu(QGraphicsSceneMouseEvent *e)
|
||||
{
|
||||
if (!isSelected() && !(e->modifiers() & Qt::ControlModifier) && m_scene)
|
||||
m_scene->unselectAll();
|
||||
|
||||
if (m_tag)
|
||||
m_tag->document()->setCurrentTag(m_tag);
|
||||
}
|
||||
|
||||
void BaseItem::createContextMenu(QMenu *menu)
|
||||
{
|
||||
if (!menu || !tag())
|
||||
return;
|
||||
|
||||
if (m_scene) {
|
||||
menu->addAction(m_scene->actionHandler()->action(ActionCopy));
|
||||
menu->addAction(m_scene->actionHandler()->action(ActionPaste));
|
||||
menu->addSeparator();
|
||||
const ScxmlUiFactory *uiFactory = m_scene->uiFactory();
|
||||
if (uiFactory) {
|
||||
auto actionProvider = static_cast<ActionProvider*>(uiFactory->object(Constants::C_UI_FACTORY_OBJECT_ACTIONPROVIDER));
|
||||
if (actionProvider) {
|
||||
actionProvider->initStateMenu(tag(), menu);
|
||||
menu->addSeparator();
|
||||
}
|
||||
}
|
||||
}
|
||||
TagUtils::createChildMenu(tag(), menu);
|
||||
}
|
||||
|
||||
void BaseItem::selectedMenuAction(const QAction *action)
|
||||
{
|
||||
if (!action)
|
||||
return;
|
||||
|
||||
ScxmlTag *tag = this->tag();
|
||||
|
||||
if (tag) {
|
||||
const QVariantMap data = action->data().toMap();
|
||||
int actionType = data.value(Constants::C_SCXMLTAG_ACTIONTYPE, -1).toInt();
|
||||
|
||||
switch (actionType) {
|
||||
case TagUtils::AddChild: {
|
||||
const ScxmlDocument *document = tag->document();
|
||||
if (m_scene && document) {
|
||||
document->undoStack()->beginMacro(tr("Add child"));
|
||||
SceneUtils::addChild(tag, data, m_scene);
|
||||
document->undoStack()->endMacro();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TagUtils::Remove:
|
||||
postDeleteEvent();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BaseItem::postDeleteEvent()
|
||||
{
|
||||
QCoreApplication::postEvent(scene(), new QKeyEvent(QEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier));
|
||||
}
|
||||
|
||||
void BaseItem::setEditorInfo(const QString &key, const QString &value, bool block)
|
||||
{
|
||||
if (m_tag && m_tag->editorInfo(key) != value) {
|
||||
if (!m_blockUpdates && !block && m_tag->document())
|
||||
m_tag->document()->setEditorInfo(m_tag, key, value);
|
||||
else
|
||||
m_tag->setEditorInfo(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
QString BaseItem::editorInfo(const QString &key) const
|
||||
{
|
||||
if (m_tag)
|
||||
return m_tag->editorInfo(key);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void BaseItem::setTagValue(const QString &key, const QString &value)
|
||||
{
|
||||
if (m_tag && m_tag->attribute(key) != value) {
|
||||
if (!m_blockUpdates && m_tag->document())
|
||||
m_tag->document()->setValue(m_tag, key, value);
|
||||
else
|
||||
m_tag->setAttribute(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
QString BaseItem::tagValue(const QString &key, bool useNameSpace) const
|
||||
{
|
||||
return m_tag ? m_tag->attribute(key, useNameSpace) : QString();
|
||||
}
|
||||
|
||||
ScxmlTag *BaseItem::tag() const
|
||||
{
|
||||
return m_tag;
|
||||
}
|
||||
|
||||
void BaseItem::setItemSelected(bool sel, bool unselectOthers)
|
||||
{
|
||||
if (sel) {
|
||||
if (unselectOthers && m_scene)
|
||||
m_scene->unselectAll();
|
||||
|
||||
if (m_tag)
|
||||
m_tag->document()->setCurrentTag(m_tag);
|
||||
} else {
|
||||
setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
QRectF BaseItem::boundingRect() const
|
||||
{
|
||||
return m_boundingRect;
|
||||
}
|
||||
|
||||
void BaseItem::setTag(ScxmlTag *tag)
|
||||
{
|
||||
m_tag = tag;
|
||||
}
|
||||
|
||||
void BaseItem::init(ScxmlTag *tag, BaseItem *parentItem, bool /*initChildren*/, bool /*blockUpdates*/)
|
||||
{
|
||||
setTag(tag);
|
||||
readUISpecifiedProperties(tag);
|
||||
setParentItem(parentItem);
|
||||
}
|
||||
|
||||
void BaseItem::setBlockUpdates(bool block)
|
||||
{
|
||||
m_blockUpdates = block;
|
||||
}
|
||||
|
||||
void BaseItem::setHighlight(bool hl)
|
||||
{
|
||||
if (hl != m_highlight) {
|
||||
m_highlight = hl;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void BaseItem::setOverlapping(bool ol)
|
||||
{
|
||||
if (ol != m_overlapping) {
|
||||
m_overlapping = ol;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
bool BaseItem::highlight() const
|
||||
{
|
||||
return m_highlight;
|
||||
}
|
||||
|
||||
bool BaseItem::overlapping() const
|
||||
{
|
||||
return m_overlapping;
|
||||
}
|
||||
|
||||
bool BaseItem::isActiveScene() const
|
||||
{
|
||||
return m_scene ? m_scene->topMostScene() : false;
|
||||
}
|
||||
|
||||
ScxmlUiFactory *BaseItem::uiFactory() const
|
||||
{
|
||||
return m_scene ? m_scene->uiFactory() : 0;
|
||||
}
|
||||
|
||||
GraphicsScene *BaseItem::graphicsScene() const
|
||||
{
|
||||
return m_scene;
|
||||
}
|
||||
|
||||
void BaseItem::setParentItem(BaseItem *item)
|
||||
{
|
||||
QGraphicsObject::setParentItem(item);
|
||||
updateColors();
|
||||
}
|
||||
|
||||
void BaseItem::checkWarnings()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseItem::checkOverlapping()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseItem::checkVisibility(double scaleFactor)
|
||||
{
|
||||
Q_UNUSED(scaleFactor)
|
||||
}
|
||||
|
||||
void BaseItem::updateUIProperties()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseItem::readUISpecifiedProperties(const ScxmlTag *tag)
|
||||
{
|
||||
Q_UNUSED(tag)
|
||||
}
|
||||
|
||||
void BaseItem::updateAttributes()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseItem::updateColors()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseItem::updateEditorInfo(bool /*allChildren*/)
|
||||
{
|
||||
readUISpecifiedProperties(m_tag);
|
||||
}
|
||||
|
||||
void BaseItem::moveStateBy(qreal /*dx*/, qreal /*dy*/)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseItem::finalizeCreation()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseItem::doLayout(int depth)
|
||||
{
|
||||
Q_UNUSED(depth)
|
||||
}
|
||||
|
||||
void BaseItem::checkInitial(bool parent)
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
}
|
||||
|
||||
bool BaseItem::containsScenePoint(const QPointF &p) const
|
||||
{
|
||||
return sceneBoundingRect().contains(p);
|
||||
}
|
||||
|
||||
QString BaseItem::itemId() const
|
||||
{
|
||||
if (m_tag) {
|
||||
if (m_tag->tagType() == Transition)
|
||||
return m_tag->attribute("event");
|
||||
else
|
||||
return m_tag->attribute("id", true);
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool BaseItem::blockUpdates() const
|
||||
{
|
||||
return m_blockUpdates;
|
||||
}
|
||||
|
||||
BaseItem *BaseItem::parentBaseItem() const
|
||||
{
|
||||
QGraphicsItem *parent = parentItem();
|
||||
return (parent && parent->type() > UnknownType)
|
||||
? qgraphicsitem_cast<BaseItem*>(parent) : nullptr;
|
||||
}
|
||||
151
src/plugins/scxmleditor/plugin_interface/baseitem.h
Normal file
151
src/plugins/scxmleditor/plugin_interface/baseitem.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mytypes.h"
|
||||
#include "scxmltag.h"
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QPointer>
|
||||
#include <QTimer>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QAction)
|
||||
QT_FORWARD_DECLARE_CLASS(QGraphicsSceneMouseEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QVariant)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
const qreal WARNING_ITEM_SIZE = 25;
|
||||
|
||||
class GraphicsScene;
|
||||
class ScxmlUiFactory;
|
||||
|
||||
/**
|
||||
* @brief The BaseItem class is the base class for every items in the scene which represent the one tag in the SCXML-tree.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class BaseItem : public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BaseItem(BaseItem *parent = nullptr);
|
||||
~BaseItem() override;
|
||||
|
||||
QRectF boundingRect() const override;
|
||||
|
||||
QPointF sceneCenter() const
|
||||
{
|
||||
return mapToScene(m_boundingRect.center());
|
||||
}
|
||||
|
||||
QString itemId() const;
|
||||
|
||||
void setItemBoundingRect(const QRectF &r);
|
||||
|
||||
QPolygonF polygonShape() const
|
||||
{
|
||||
return m_polygon;
|
||||
}
|
||||
|
||||
void updateDepth();
|
||||
int depth() const
|
||||
{
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
void setParentItem(BaseItem *item);
|
||||
virtual void checkWarnings();
|
||||
virtual void checkOverlapping();
|
||||
virtual void checkVisibility(double scaleFactor);
|
||||
virtual void setTag(ScxmlTag *tag);
|
||||
virtual void init(ScxmlTag *tag, BaseItem *parentItem = nullptr, bool initChildren = true, bool blockUpdates = false);
|
||||
virtual void updateAttributes();
|
||||
virtual void updateColors();
|
||||
virtual void updateEditorInfo(bool allChildren = false);
|
||||
virtual void moveStateBy(qreal dx, qreal dy);
|
||||
virtual ScxmlTag *tag() const;
|
||||
virtual void finalizeCreation();
|
||||
virtual void doLayout(int depth);
|
||||
virtual void setHighlight(bool hl);
|
||||
virtual void checkInitial(bool parent = false);
|
||||
virtual bool containsScenePoint(const QPointF &p) const;
|
||||
|
||||
void setEditorInfo(const QString &key, const QString &value, bool block = false);
|
||||
QString editorInfo(const QString &key) const;
|
||||
|
||||
void setTagValue(const QString &key, const QString &value);
|
||||
QString tagValue(const QString &key, bool useNameSpace = false) const;
|
||||
|
||||
void setBlockUpdates(bool block);
|
||||
void setOverlapping(bool ol);
|
||||
bool blockUpdates() const;
|
||||
bool highlight() const;
|
||||
bool overlapping() const;
|
||||
|
||||
BaseItem *parentBaseItem() const;
|
||||
bool isActiveScene() const;
|
||||
GraphicsScene *graphicsScene() const;
|
||||
ScxmlUiFactory *uiFactory() const;
|
||||
|
||||
virtual void updateUIProperties();
|
||||
|
||||
protected:
|
||||
virtual void updatePolygon();
|
||||
void setItemSelected(bool sel, bool unselectOthers = true);
|
||||
|
||||
signals:
|
||||
void geometryChanged();
|
||||
void selectedStateChanged(bool sel);
|
||||
void openToDifferentView(BaseItem *item);
|
||||
|
||||
protected:
|
||||
void postDeleteEvent();
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *e) override;
|
||||
void showContextMenu(QGraphicsSceneMouseEvent *e);
|
||||
virtual void checkSelectionBeforeContextMenu(QGraphicsSceneMouseEvent *e);
|
||||
virtual void createContextMenu(QMenu *menu);
|
||||
virtual void selectedMenuAction(const QAction *action);
|
||||
virtual void readUISpecifiedProperties(const ScxmlTag *tag);
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
void checkParentBoundingRect();
|
||||
QPolygonF m_polygon;
|
||||
|
||||
private:
|
||||
QRectF m_boundingRect;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
QPointer<GraphicsScene> m_scene;
|
||||
bool m_blockUpdates = false;
|
||||
int m_depth = 0;
|
||||
bool m_highlight = false;
|
||||
bool m_overlapping = false;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
809
src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
Normal file
809
src/plugins/scxmleditor/plugin_interface/connectableitem.cpp
Normal file
@@ -0,0 +1,809 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "connectableitem.h"
|
||||
#include "cornergrabberitem.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "highlightitem.h"
|
||||
#include "quicktransitionitem.h"
|
||||
#include "sceneutils.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "serializer.h"
|
||||
#include "stateitem.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
#include <QStringList>
|
||||
#include <QUndoStack>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ConnectableItem::ConnectableItem(const QPointF &p, BaseItem *parent)
|
||||
: BaseItem(parent)
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemIsMovable, true);
|
||||
setFlag(QGraphicsItem::ItemIsSelectable, true);
|
||||
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
||||
setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
|
||||
setAcceptDrops(true);
|
||||
|
||||
m_selectedPen.setStyle(Qt::DotLine);
|
||||
m_selectedPen.setColor(QColor(0x44, 0x44, 0xed));
|
||||
m_selectedPen.setCosmetic(true);
|
||||
m_releasedFromParentBrush = QBrush(QColor(0x98, 0x98, 0x98));
|
||||
|
||||
setPos(p);
|
||||
connect(this, &ConnectableItem::geometryChanged, this, &ConnectableItem::updateCornerPositions);
|
||||
}
|
||||
|
||||
ConnectableItem::~ConnectableItem()
|
||||
{
|
||||
setBlockUpdates(true);
|
||||
|
||||
foreach (ConnectableItem *item, m_overlappedItems) {
|
||||
item->removeOverlappingItem(this);
|
||||
}
|
||||
m_overlappedItems.clear();
|
||||
|
||||
foreach (TransitionItem *transition, m_outputTransitions) {
|
||||
transition->disconnectItem(this);
|
||||
}
|
||||
m_outputTransitions.clear();
|
||||
|
||||
foreach (TransitionItem *transition, m_inputTransitions) {
|
||||
transition->disconnectItem(this);
|
||||
}
|
||||
m_inputTransitions.clear();
|
||||
|
||||
qDeleteAll(m_quickTransitions);
|
||||
m_quickTransitions.clear();
|
||||
}
|
||||
|
||||
void ConnectableItem::createCorners()
|
||||
{
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
Qt::CursorShape cur = Qt::SizeHorCursor;
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 4:
|
||||
cur = Qt::SizeFDiagCursor;
|
||||
break;
|
||||
case 1:
|
||||
case 5:
|
||||
cur = Qt::SizeVerCursor;
|
||||
break;
|
||||
case 2:
|
||||
case 6:
|
||||
cur = Qt::SizeBDiagCursor;
|
||||
break;
|
||||
case 3:
|
||||
case 7:
|
||||
cur = Qt::SizeHorCursor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_corners << new CornerGrabberItem(this, cur);
|
||||
}
|
||||
|
||||
qDeleteAll(m_quickTransitions);
|
||||
m_quickTransitions.clear();
|
||||
m_quickTransitions << new QuickTransitionItem(0, UnknownType, this);
|
||||
m_quickTransitions << new QuickTransitionItem(1, StateType, this);
|
||||
m_quickTransitions << new QuickTransitionItem(2, ParallelType, this);
|
||||
m_quickTransitions << new QuickTransitionItem(3, HistoryType, this);
|
||||
m_quickTransitions << new QuickTransitionItem(4, FinalStateType, this);
|
||||
|
||||
updateCornerPositions();
|
||||
}
|
||||
|
||||
void ConnectableItem::removeCorners()
|
||||
{
|
||||
qDeleteAll(m_corners);
|
||||
m_corners.clear();
|
||||
|
||||
qDeleteAll(m_quickTransitions);
|
||||
m_quickTransitions.clear();
|
||||
}
|
||||
|
||||
void ConnectableItem::updateCornerPositions()
|
||||
{
|
||||
QRectF r = boundingRect();
|
||||
if (m_corners.count() == 8) {
|
||||
qreal cx = r.center().x();
|
||||
qreal cy = r.center().y();
|
||||
m_corners[0]->setPos(r.topLeft());
|
||||
m_corners[1]->setPos(cx, r.top());
|
||||
m_corners[2]->setPos(r.topRight());
|
||||
m_corners[3]->setPos(r.right(), cy);
|
||||
m_corners[4]->setPos(r.bottomRight());
|
||||
m_corners[5]->setPos(cx, r.bottom());
|
||||
m_corners[6]->setPos(r.bottomLeft());
|
||||
m_corners[7]->setPos(r.left(), cy);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_quickTransitions.count(); ++i) {
|
||||
m_quickTransitions[i]->setPos(r.topLeft());
|
||||
m_quickTransitions[i]->setVisible(!m_releasedFromParent && canStartTransition(m_quickTransitions[i]->connectionType()));
|
||||
}
|
||||
updateShadowClipRegion();
|
||||
}
|
||||
|
||||
bool ConnectableItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
||||
{
|
||||
if (watched->type() == CornerGrabberType) {
|
||||
auto c = qgraphicsitem_cast<CornerGrabberItem*>(watched);
|
||||
auto mouseEvent = dynamic_cast<QGraphicsSceneMouseEvent*>(event);
|
||||
if (c == nullptr || mouseEvent == nullptr)
|
||||
return BaseItem::sceneEventFilter(watched, event);
|
||||
|
||||
QRectF r = boundingRect();
|
||||
if (event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
setOpacity(0.5);
|
||||
} else if (event->type() == QEvent::GraphicsSceneMouseMove) {
|
||||
QPointF pw = watched->mapToItem(this, mouseEvent->pos());
|
||||
QRectF rMin;
|
||||
if (type() >= StateType)
|
||||
rMin = qgraphicsitem_cast<StateItem*>(this)->childItemsBoundingRect();
|
||||
if (rMin.isNull()) {
|
||||
rMin = QRectF(0, 0, m_minimumWidth, m_minimumHeight);
|
||||
rMin.moveCenter(r.center());
|
||||
}
|
||||
|
||||
switch (m_corners.indexOf(c)) {
|
||||
case 0:
|
||||
r.setTopLeft(QPointF(qMin(pw.x(), rMin.left()), qMin(pw.y(), rMin.top())));
|
||||
break;
|
||||
case 1:
|
||||
r.setTop(qMin(pw.y(), rMin.top()));
|
||||
break;
|
||||
case 2:
|
||||
r.setTopRight(QPointF(qMax(pw.x(), rMin.right()), qMin(pw.y(), rMin.top())));
|
||||
break;
|
||||
case 3:
|
||||
r.setRight(qMax(pw.x(), rMin.right()));
|
||||
break;
|
||||
case 4:
|
||||
r.setBottomRight(QPointF(qMax(pw.x(), rMin.right()), qMax(pw.y(), rMin.bottom())));
|
||||
break;
|
||||
case 5:
|
||||
r.setBottom(qMax(pw.y(), rMin.bottom()));
|
||||
break;
|
||||
case 6:
|
||||
r.setBottomLeft(QPointF(qMin(pw.x(), rMin.left()), qMax(pw.y(), rMin.bottom())));
|
||||
break;
|
||||
case 7:
|
||||
r.setLeft(qMin(pw.x(), rMin.left()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setItemBoundingRect(r);
|
||||
updateCornerPositions();
|
||||
updateTransitions();
|
||||
|
||||
return true;
|
||||
} else if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
setOpacity(1.0);
|
||||
updateUIProperties();
|
||||
checkOverlapping();
|
||||
}
|
||||
} else if (watched->type() == QuickTransitionType) {
|
||||
auto mouseEvent = dynamic_cast<QGraphicsSceneMouseEvent*>(event);
|
||||
if (!mouseEvent)
|
||||
return BaseItem::sceneEventFilter(watched, event);
|
||||
|
||||
if (event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
m_newTransitionStartedPoint = mouseEvent->pos();
|
||||
tag()->document()->undoStack()->beginMacro(tr("Add new state"));
|
||||
|
||||
m_newTransition = new TransitionItem;
|
||||
scene()->addItem(m_newTransition);
|
||||
|
||||
ScxmlTag *newTag = nullptr;
|
||||
if (tag()->tagType() == Initial || tag()->tagType() == History)
|
||||
newTag = new ScxmlTag(InitialTransition, tag()->document());
|
||||
else
|
||||
newTag = new ScxmlTag(Transition, tag()->document());
|
||||
newTag->setAttribute("type", "external");
|
||||
m_newTransition->init(newTag);
|
||||
|
||||
tag()->document()->addTag(tag(), newTag);
|
||||
m_newTransition->startTransitionFrom(this, watched->mapToScene(mouseEvent->pos()));
|
||||
return true;
|
||||
} else if (event->type() == QEvent::GraphicsSceneMouseMove) {
|
||||
if (m_newTransition)
|
||||
m_newTransition->setEndPos(watched->mapToScene(mouseEvent->pos()));
|
||||
} else if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
auto tra = qgraphicsitem_cast<QuickTransitionItem*>(watched);
|
||||
if (!tra)
|
||||
return BaseItem::sceneEventFilter(watched, event);
|
||||
|
||||
if (m_newTransition) {
|
||||
QLineF line(m_newTransitionStartedPoint, mouseEvent->pos());
|
||||
if (line.length() > 30) {
|
||||
m_newTransition->connectToTopItem(watched->mapToScene(mouseEvent->pos()), TransitionItem::End, tra->connectionType());
|
||||
m_newTransition = nullptr;
|
||||
setSelected(false);
|
||||
tag()->document()->undoStack()->endMacro();
|
||||
} else {
|
||||
m_newTransition->grabMouse(tra->connectionType());
|
||||
m_newTransition = nullptr;
|
||||
setSelected(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BaseItem::sceneEventFilter(watched, event);
|
||||
}
|
||||
|
||||
void ConnectableItem::addOutputTransition(TransitionItem *transition)
|
||||
{
|
||||
m_outputTransitions.append(transition);
|
||||
transitionCountChanged();
|
||||
}
|
||||
|
||||
void ConnectableItem::addInputTransition(TransitionItem *transition)
|
||||
{
|
||||
m_inputTransitions.append(transition);
|
||||
transitionCountChanged();
|
||||
}
|
||||
|
||||
void ConnectableItem::removeOutputTransition(TransitionItem *transition)
|
||||
{
|
||||
m_outputTransitions.removeAll(transition);
|
||||
transitionCountChanged();
|
||||
}
|
||||
|
||||
void ConnectableItem::removeInputTransition(TransitionItem *transition)
|
||||
{
|
||||
m_inputTransitions.removeAll(transition);
|
||||
transitionCountChanged();
|
||||
}
|
||||
|
||||
void ConnectableItem::updateInputTransitions()
|
||||
{
|
||||
foreach (TransitionItem *transition, m_inputTransitions) {
|
||||
transition->updateComponents();
|
||||
transition->updateUIProperties();
|
||||
}
|
||||
transitionsChanged();
|
||||
}
|
||||
|
||||
void ConnectableItem::updateOutputTransitions()
|
||||
{
|
||||
foreach (TransitionItem *transition, m_outputTransitions) {
|
||||
transition->updateComponents();
|
||||
transition->updateUIProperties();
|
||||
}
|
||||
transitionsChanged();
|
||||
}
|
||||
|
||||
void ConnectableItem::updateTransitions(bool allChildren)
|
||||
{
|
||||
updateOutputTransitions();
|
||||
updateInputTransitions();
|
||||
|
||||
if (allChildren) {
|
||||
foreach (QGraphicsItem *it, childItems()) {
|
||||
auto item = static_cast<ConnectableItem*>(it);
|
||||
if (item && item->type() >= InitialStateType)
|
||||
item->updateTransitions(allChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectableItem::updateTransitionAttributes(bool allChildren)
|
||||
{
|
||||
foreach (TransitionItem *transition, m_outputTransitions)
|
||||
transition->updateTarget();
|
||||
|
||||
foreach (TransitionItem *transition, m_inputTransitions)
|
||||
transition->updateTarget();
|
||||
|
||||
if (allChildren) {
|
||||
foreach (QGraphicsItem *it, childItems()) {
|
||||
auto item = static_cast<ConnectableItem*>(it);
|
||||
if (item && item->type() >= InitialStateType)
|
||||
item->updateTransitionAttributes(allChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectableItem::transitionsChanged()
|
||||
{
|
||||
}
|
||||
|
||||
void ConnectableItem::transitionCountChanged()
|
||||
{
|
||||
}
|
||||
|
||||
QPointF ConnectableItem::getInternalPosition(const TransitionItem *transition, TransitionItem::TransitionTargetType type) const
|
||||
{
|
||||
const QRectF srect = sceneBoundingRect();
|
||||
|
||||
int ind = 0;
|
||||
if (type == TransitionItem::InternalNoTarget) {
|
||||
foreach (TransitionItem *item, m_outputTransitions) {
|
||||
if (item->targetType() == TransitionItem::InternalSameTarget)
|
||||
ind++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_outputTransitions.count(); ++i) {
|
||||
TransitionItem *item = m_outputTransitions[i];
|
||||
if (item == transition)
|
||||
break;
|
||||
else if (item->targetType() == type)
|
||||
ind++;
|
||||
}
|
||||
|
||||
return QPointF(srect.left() + 20, srect.top() + srect.height() * 0.06 + 40 + ind * 30);
|
||||
}
|
||||
|
||||
void ConnectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
// We want to pan scene when Shift is pressed -> that's why ignore mouse-event here
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
BaseItem::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void ConnectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
// We want to pan scene when Shift is pressed -> that's why ignore mouse-event here
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_moveMacroStarted) {
|
||||
m_moveMacroStarted = true;
|
||||
tag()->document()->undoStack()->beginMacro(tr("Move State"));
|
||||
}
|
||||
|
||||
//Restore old behavior if ctrl & alt modifiers are present
|
||||
if (!m_releasedFromParent && !(event->modifiers() & Qt::AltModifier) && !(event->modifiers() & Qt::ControlModifier)) {
|
||||
releaseFromParent();
|
||||
foreach (QGraphicsItem *it, scene()->selectedItems()) {
|
||||
if (it->type() >= InitialStateType && it != this) {
|
||||
qgraphicsitem_cast<ConnectableItem*>(it)->releaseFromParent();
|
||||
}
|
||||
}
|
||||
} else
|
||||
setOpacity(0.5);
|
||||
|
||||
BaseItem::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void ConnectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
// We want to pan scene when Shift is pressed -> that's why ignore mouse-event here
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
BaseItem::mouseReleaseEvent(event);
|
||||
|
||||
if (m_releasedFromParent) {
|
||||
// Try to find parent
|
||||
QList<QGraphicsItem*> parentItems = scene()->items(event->scenePos());
|
||||
BaseItem *parentItem = nullptr;
|
||||
for (int i = 0; i < parentItems.count(); ++i) {
|
||||
auto item = static_cast<BaseItem*>(parentItems[i]);
|
||||
if (item && item != this && !item->isSelected()
|
||||
&& item->type() >= StateType
|
||||
&& SceneUtils::canDrop(item->type(), type())) {
|
||||
parentItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
connectToParent(parentItem);
|
||||
foreach (QGraphicsItem *it, scene()->selectedItems()) {
|
||||
if (it->type() >= InitialStateType && it != this)
|
||||
qgraphicsitem_cast<ConnectableItem*>(it)->connectToParent(parentItem);
|
||||
}
|
||||
} else
|
||||
setOpacity(1.0);
|
||||
|
||||
if (m_moveMacroStarted) {
|
||||
m_moveMacroStarted = false;
|
||||
tag()->document()->undoStack()->endMacro();
|
||||
}
|
||||
|
||||
checkOverlapping();
|
||||
}
|
||||
|
||||
void ConnectableItem::releaseFromParent()
|
||||
{
|
||||
m_releasedFromParent = true;
|
||||
setOpacity(0.5);
|
||||
m_releasedIndex = tag()->index();
|
||||
m_releasedParent = parentItem();
|
||||
tag()->document()->changeParent(tag(), 0, m_releasedParent == nullptr ? m_releasedIndex : -1);
|
||||
setZValue(503);
|
||||
|
||||
for (int i = 0; i < m_quickTransitions.count(); ++i)
|
||||
m_quickTransitions[i]->setVisible(false);
|
||||
for (int i = 0; i < m_corners.count(); ++i)
|
||||
m_corners[i]->setVisible(false);
|
||||
update();
|
||||
}
|
||||
|
||||
void ConnectableItem::connectToParent(BaseItem *parentItem)
|
||||
{
|
||||
for (int i = 0; i < m_quickTransitions.count(); ++i)
|
||||
m_quickTransitions[i]->setVisible(canStartTransition(m_quickTransitions[i]->connectionType()));
|
||||
for (int i = 0; i < m_corners.count(); ++i)
|
||||
m_corners[i]->setVisible(true);
|
||||
|
||||
tag()->document()->changeParent(tag(), parentItem ? parentItem->tag() : 0, parentItem == m_releasedParent ? m_releasedIndex : -1);
|
||||
|
||||
setZValue(0);
|
||||
m_releasedIndex = -1;
|
||||
m_releasedParent = nullptr;
|
||||
m_releasedFromParent = false;
|
||||
setOpacity(1.0);
|
||||
}
|
||||
|
||||
QVariant ConnectableItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
switch (change) {
|
||||
case ItemSelectedHasChanged: {
|
||||
if (value.toBool()) {
|
||||
createCorners();
|
||||
SceneUtils::moveTop(this, static_cast<GraphicsScene*>(scene()));
|
||||
} else
|
||||
removeCorners();
|
||||
break;
|
||||
}
|
||||
case ItemParentHasChanged:
|
||||
updateTransitions(true);
|
||||
updateTransitionAttributes(true);
|
||||
// FIXME: intended fallthrough?
|
||||
case ItemPositionHasChanged:
|
||||
if (!m_releasedFromParent && !blockUpdates())
|
||||
checkParentBoundingRect();
|
||||
break;
|
||||
case ItemScenePositionHasChanged:
|
||||
updateTransitions();
|
||||
if (m_highlighItem)
|
||||
m_highlighItem->advance(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return BaseItem::itemChange(change, value);
|
||||
}
|
||||
|
||||
qreal ConnectableItem::getOpacity()
|
||||
{
|
||||
if (opacity() < 1.0)
|
||||
return opacity();
|
||||
|
||||
if (overlapping())
|
||||
return 0.5;
|
||||
|
||||
if (parentBaseItem())
|
||||
if (parentBaseItem()->type() >= InitialStateType)
|
||||
return static_cast<ConnectableItem*>(parentBaseItem())->getOpacity();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ConnectableItem::updateShadowClipRegion()
|
||||
{
|
||||
QPainterPath br, sr;
|
||||
//StateItem Background rounded rectangle
|
||||
br.addRoundedRect(boundingRect().adjusted(5, 5, -5, -5), 10, 10);
|
||||
//Shadow rounded rectangle
|
||||
sr.addRoundedRect(boundingRect().adjusted(10, 10, 0, 0), 10, 10);
|
||||
//Clippath is subtract
|
||||
m_shadowClipPath = sr - br;
|
||||
}
|
||||
|
||||
void ConnectableItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(widget)
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setOpacity(getOpacity());
|
||||
|
||||
if (m_releasedFromParent) {
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(m_releasedFromParentBrush);
|
||||
painter->setClipping(true);
|
||||
painter->setClipPath(m_shadowClipPath);
|
||||
//Since the form is already cliped just draw a rectangle
|
||||
painter->drawRect(boundingRect().adjusted(10, 10, 0, 0));
|
||||
painter->setClipping(false);
|
||||
}
|
||||
|
||||
if (isSelected()) {
|
||||
painter->setPen(m_selectedPen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawRect(boundingRect());
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void ConnectableItem::updateUIProperties()
|
||||
{
|
||||
if (tag() != 0 && isActiveScene()) {
|
||||
Serializer s;
|
||||
s.append(pos());
|
||||
s.append(boundingRect());
|
||||
setEditorInfo(Constants::C_SCXML_EDITORINFO_GEOMETRY, s.data());
|
||||
s.clear();
|
||||
s.append(scenePos());
|
||||
s.append(sceneBoundingRect());
|
||||
setEditorInfo("scenegeometry", s.data());
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectableItem::updateAttributes()
|
||||
{
|
||||
BaseItem::updateAttributes();
|
||||
|
||||
foreach (TransitionItem *transition, m_inputTransitions) {
|
||||
if (transition->isEndItem(this))
|
||||
transition->setTagValue("target", itemId());
|
||||
}
|
||||
updateInputTransitions();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void ConnectableItem::updateEditorInfo(bool allChildren)
|
||||
{
|
||||
BaseItem::updateEditorInfo(allChildren);
|
||||
updateTransitions();
|
||||
}
|
||||
|
||||
void ConnectableItem::moveStateBy(qreal dx, qreal dy)
|
||||
{
|
||||
moveBy(dx, dy);
|
||||
updateUIProperties();
|
||||
updateTransitions();
|
||||
}
|
||||
|
||||
void ConnectableItem::setHighlight(bool hl)
|
||||
{
|
||||
BaseItem::setHighlight(hl);
|
||||
if (highlight()) {
|
||||
if (!m_highlighItem) {
|
||||
m_highlighItem = new HighlightItem(this);
|
||||
scene()->addItem(m_highlighItem);
|
||||
}
|
||||
} else {
|
||||
delete m_highlighItem;
|
||||
m_highlighItem = nullptr;
|
||||
}
|
||||
|
||||
if (m_highlighItem)
|
||||
m_highlighItem->advance(0);
|
||||
}
|
||||
|
||||
void ConnectableItem::readUISpecifiedProperties(const ScxmlTag *tag)
|
||||
{
|
||||
if (tag) {
|
||||
QString data = editorInfo(Constants::C_SCXML_EDITORINFO_GEOMETRY);
|
||||
if (!data.isEmpty()) {
|
||||
QPointF p(0, 0);
|
||||
QRectF r(-60, 50, 120, 100);
|
||||
|
||||
Serializer s;
|
||||
s.setData(data);
|
||||
s.read(p);
|
||||
s.read(r);
|
||||
|
||||
setItemBoundingRect(r);
|
||||
setPos(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectableItem::addTransitions(const ScxmlTag *tag)
|
||||
{
|
||||
if (scene()) {
|
||||
for (int i = 0; i < tag->childCount(); ++i) {
|
||||
ScxmlTag *child = tag->child(i);
|
||||
if (child->tagType() == Transition || child->tagType() == InitialTransition) {
|
||||
auto transition = new TransitionItem;
|
||||
scene()->addItem(transition);
|
||||
transition->setStartItem(this);
|
||||
transition->init(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectableItem::init(ScxmlTag *tag, BaseItem *parentItem, bool initChildren, bool /*blockUpdates*/)
|
||||
{
|
||||
BaseItem::init(tag, parentItem);
|
||||
if (initChildren)
|
||||
addTransitions(tag);
|
||||
}
|
||||
|
||||
void ConnectableItem::setMinimumWidth(int width)
|
||||
{
|
||||
m_minimumWidth = width;
|
||||
QRectF r = boundingRect();
|
||||
if (r.width() < width) {
|
||||
r.setWidth(width);
|
||||
setItemBoundingRect(r);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectableItem::setMinimumHeight(int height)
|
||||
{
|
||||
m_minimumHeight = height;
|
||||
QRectF r = boundingRect();
|
||||
if (r.height() < height) {
|
||||
r.setHeight(height);
|
||||
setItemBoundingRect(r);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectableItem::finalizeCreation()
|
||||
{
|
||||
bool old = blockUpdates();
|
||||
setBlockUpdates(true);
|
||||
|
||||
updateAttributes();
|
||||
updateEditorInfo();
|
||||
updateUIProperties();
|
||||
checkInitial(true);
|
||||
|
||||
if (!old)
|
||||
setBlockUpdates(false);
|
||||
}
|
||||
|
||||
bool ConnectableItem::hasInputTransitions(const ConnectableItem *parentItem, bool checkChildren) const
|
||||
{
|
||||
foreach (const TransitionItem *it, m_inputTransitions) {
|
||||
if (!SceneUtils::isChild(parentItem, it->connectedItem(this)))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (checkChildren) {
|
||||
foreach (QGraphicsItem *it, childItems()) {
|
||||
if (it->type() >= InitialStateType) {
|
||||
auto item = qgraphicsitem_cast<ConnectableItem*>(it);
|
||||
if (item && item->hasInputTransitions(parentItem, checkChildren))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConnectableItem::hasOutputTransitions(const ConnectableItem *parentItem, bool checkChildren) const
|
||||
{
|
||||
foreach (TransitionItem *it, m_outputTransitions) {
|
||||
if (!SceneUtils::isChild(parentItem, it->connectedItem(this)))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (checkChildren) {
|
||||
foreach (QGraphicsItem *it, childItems()) {
|
||||
if (it->type() >= InitialStateType) {
|
||||
auto item = qgraphicsitem_cast<ConnectableItem*>(it);
|
||||
if (item && item->hasOutputTransitions(parentItem, checkChildren))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectableItem::addOverlappingItem(ConnectableItem *item)
|
||||
{
|
||||
if (!m_overlappedItems.contains(item))
|
||||
m_overlappedItems.append(item);
|
||||
|
||||
setOverlapping(m_overlappedItems.count() > 0);
|
||||
}
|
||||
|
||||
void ConnectableItem::removeOverlappingItem(ConnectableItem *item)
|
||||
{
|
||||
if (m_overlappedItems.contains(item))
|
||||
m_overlappedItems.removeAll(item);
|
||||
|
||||
setOverlapping(m_overlappedItems.count() > 0);
|
||||
}
|
||||
|
||||
void ConnectableItem::checkOverlapping()
|
||||
{
|
||||
QVector<ConnectableItem*> overlappedItems;
|
||||
foreach (QGraphicsItem *it, collidingItems()) {
|
||||
if (it->type() >= InitialStateType && it->parentItem() == parentItem()) {
|
||||
overlappedItems << qgraphicsitem_cast<ConnectableItem*>(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unnecessary items
|
||||
for (int i = m_overlappedItems.count(); i--;) {
|
||||
if (!overlappedItems.contains(m_overlappedItems[i])) {
|
||||
m_overlappedItems[i]->removeOverlappingItem(this);
|
||||
m_overlappedItems.removeAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new overlapped items
|
||||
foreach (ConnectableItem *it, overlappedItems) {
|
||||
if (!m_overlappedItems.contains(it)) {
|
||||
m_overlappedItems << it;
|
||||
it->addOverlappingItem(this);
|
||||
}
|
||||
}
|
||||
|
||||
setOverlapping(m_overlappedItems.count() > 0);
|
||||
}
|
||||
|
||||
bool ConnectableItem::canStartTransition(ItemType type) const
|
||||
{
|
||||
Q_UNUSED(type)
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<TransitionItem*> ConnectableItem::outputTransitions() const
|
||||
{
|
||||
return m_outputTransitions;
|
||||
}
|
||||
|
||||
QVector<TransitionItem*> ConnectableItem::inputTransitions() const
|
||||
{
|
||||
return m_inputTransitions;
|
||||
}
|
||||
|
||||
int ConnectableItem::transitionCount() const
|
||||
{
|
||||
return m_outputTransitions.count() + m_inputTransitions.count();
|
||||
}
|
||||
|
||||
int ConnectableItem::outputTransitionCount() const
|
||||
{
|
||||
return m_outputTransitions.count();
|
||||
}
|
||||
|
||||
int ConnectableItem::inputTransitionCount() const
|
||||
{
|
||||
return m_inputTransitions.count();
|
||||
}
|
||||
146
src/plugins/scxmleditor/plugin_interface/connectableitem.h
Normal file
146
src/plugins/scxmleditor/plugin_interface/connectableitem.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
#include "transitionitem.h"
|
||||
|
||||
#include <QPen>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QGraphicsSceneMouseEvent)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class CornerGrabberItem;
|
||||
class HighlightItem;
|
||||
class QuickTransitionItem;
|
||||
|
||||
/**
|
||||
* @brief The ConnectableItem class is the base class for all draggable state-items.
|
||||
*/
|
||||
class ConnectableItem : public BaseItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConnectableItem(const QPointF &pos, BaseItem *parent = nullptr);
|
||||
~ConnectableItem() override;
|
||||
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
|
||||
|
||||
void addOutputTransition(TransitionItem *transition);
|
||||
void addInputTransition(TransitionItem *transition);
|
||||
void removeOutputTransition(TransitionItem *transition);
|
||||
void removeInputTransition(TransitionItem *transition);
|
||||
QVector<TransitionItem*> outputTransitions() const;
|
||||
QVector<TransitionItem*> inputTransitions() const;
|
||||
|
||||
void setMinimumWidth(int width);
|
||||
void setMinimumHeight(int height);
|
||||
int minHeight() const
|
||||
{
|
||||
return m_minimumHeight;
|
||||
}
|
||||
|
||||
int minWidth() const
|
||||
{
|
||||
return m_minimumWidth;
|
||||
}
|
||||
|
||||
void finalizeCreation() override;
|
||||
void init(ScxmlTag *tag, BaseItem *parentItem = nullptr, bool initChildren = true, bool blockUpdates = false) override;
|
||||
|
||||
void updateUIProperties() override;
|
||||
void updateAttributes() override;
|
||||
void updateEditorInfo(bool allChildren = false) override;
|
||||
void moveStateBy(qreal dx, qreal dy) override;
|
||||
void setHighlight(bool hl) override;
|
||||
|
||||
int transitionCount() const;
|
||||
int outputTransitionCount() const;
|
||||
int inputTransitionCount() const;
|
||||
bool hasInputTransitions(const ConnectableItem *parentItem, bool checkChildren = false) const;
|
||||
bool hasOutputTransitions(const ConnectableItem *parentItem, bool checkChildren = false) const;
|
||||
QPointF getInternalPosition(const TransitionItem *transition, TransitionItem::TransitionTargetType type) const;
|
||||
|
||||
void updateOutputTransitions();
|
||||
void updateInputTransitions();
|
||||
void updateTransitions(bool allChildren = false);
|
||||
void updateTransitionAttributes(bool allChildren = false);
|
||||
|
||||
void addOverlappingItem(ConnectableItem *item);
|
||||
void removeOverlappingItem(ConnectableItem *item);
|
||||
void checkOverlapping() override;
|
||||
|
||||
// Parent change
|
||||
virtual void releaseFromParent();
|
||||
virtual void connectToParent(BaseItem *parentItem);
|
||||
|
||||
qreal getOpacity();
|
||||
|
||||
protected:
|
||||
void readUISpecifiedProperties(const ScxmlTag *tag) override;
|
||||
void addTransitions(const ScxmlTag *tag);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
virtual bool canStartTransition(ItemType type) const;
|
||||
virtual void transitionCountChanged();
|
||||
virtual void transitionsChanged();
|
||||
|
||||
private:
|
||||
void updateCornerPositions();
|
||||
void createCorners();
|
||||
void removeCorners();
|
||||
void updateShadowClipRegion();
|
||||
|
||||
QVector<TransitionItem*> m_outputTransitions;
|
||||
QVector<TransitionItem*> m_inputTransitions;
|
||||
QVector<CornerGrabberItem*> m_corners;
|
||||
QVector<QuickTransitionItem*> m_quickTransitions;
|
||||
HighlightItem *m_highlighItem = nullptr;
|
||||
TransitionItem *m_newTransition = nullptr;
|
||||
QPen m_selectedPen;
|
||||
QBrush m_releasedFromParentBrush;
|
||||
int m_minimumWidth = 120;
|
||||
int m_minimumHeight = 100;
|
||||
bool m_releasedFromParent = false;
|
||||
int m_releasedIndex = -1;
|
||||
QGraphicsItem *m_releasedParent = nullptr;
|
||||
QPointF m_newTransitionStartedPoint;
|
||||
QPainterPath m_shadowClipPath;
|
||||
QPointF m_moveStartPoint;
|
||||
bool m_moveMacroStarted = false;
|
||||
QVector<ConnectableItem*> m_overlappedItems;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,93 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cornergrabberitem.h"
|
||||
|
||||
#include <QCursor>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
CornerGrabberItem::CornerGrabberItem(QGraphicsItem *parent, Qt::CursorShape cshape)
|
||||
: QGraphicsObject(parent)
|
||||
, m_cursorShape(cshape)
|
||||
{
|
||||
setFlag(ItemIgnoresTransformations, true);
|
||||
setParentItem(parent);
|
||||
installSceneEventFilter(parent);
|
||||
setZValue(500);
|
||||
m_rect = QRectF(-5, -5, 10, 10);
|
||||
m_drawingRect = m_rect.adjusted(2, 2, -2, -2);
|
||||
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
void CornerGrabberItem::updateCursor()
|
||||
{
|
||||
setCursor(m_selected ? m_cursorShape : Qt::ArrowCursor);
|
||||
}
|
||||
|
||||
void CornerGrabberItem::setSelected(bool para)
|
||||
{
|
||||
m_selected = para;
|
||||
updateCursor();
|
||||
update();
|
||||
}
|
||||
|
||||
void CornerGrabberItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
Q_UNUSED(e)
|
||||
setSelected(false);
|
||||
}
|
||||
|
||||
void CornerGrabberItem::hoverEnterEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
Q_UNUSED(e)
|
||||
setSelected(true);
|
||||
}
|
||||
|
||||
void CornerGrabberItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
|
||||
{
|
||||
m_pressPoint = e->pos();
|
||||
}
|
||||
|
||||
void CornerGrabberItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(widget)
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(isEnabled() ? QColor(0x62, 0x62, 0xf9) : QColor(0x12, 0x12, 0x12));
|
||||
|
||||
if (m_grabberType == Square)
|
||||
painter->drawRect(m_drawingRect);
|
||||
else
|
||||
painter->drawEllipse(m_drawingRect);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
96
src/plugins/scxmleditor/plugin_interface/cornergrabberitem.h
Normal file
96
src/plugins/scxmleditor/plugin_interface/cornergrabberitem.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QGraphicsSceneHoverEvent)
|
||||
QT_FORWARD_DECLARE_CLASS(QGraphicsSceneMouseEvent)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The CornerGrabberItem class provides the way to connect/create item(s) straight from the second item.
|
||||
*
|
||||
*/
|
||||
class CornerGrabberItem : public QGraphicsObject
|
||||
{
|
||||
public:
|
||||
explicit CornerGrabberItem(QGraphicsItem *parent, Qt::CursorShape cshape = Qt::PointingHandCursor);
|
||||
|
||||
enum GrabberType {
|
||||
Square,
|
||||
Circle
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief type of the item
|
||||
*/
|
||||
int type() const override
|
||||
{
|
||||
return CornerGrabberType;
|
||||
}
|
||||
|
||||
QRectF boundingRect() const override
|
||||
{
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
QPointF pressedPoint()
|
||||
{
|
||||
return m_pressPoint;
|
||||
}
|
||||
|
||||
void setGrabberType(GrabberType type)
|
||||
{
|
||||
m_grabberType = type;
|
||||
}
|
||||
|
||||
void setSelected(bool para);
|
||||
bool isSelected() const
|
||||
{
|
||||
return m_selected;
|
||||
}
|
||||
|
||||
private:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *e) override;
|
||||
void updateCursor();
|
||||
|
||||
QRectF m_rect, m_drawingRect;
|
||||
QPointF m_pressPoint;
|
||||
GrabberType m_grabberType = Square;
|
||||
Qt::CursorShape m_cursorShape;
|
||||
bool m_selected = false;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
80
src/plugins/scxmleditor/plugin_interface/finalstateitem.cpp
Normal file
80
src/plugins/scxmleditor/plugin_interface/finalstateitem.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "finalstateitem.h"
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
FinalStateItem::FinalStateItem(const QPointF &pos, BaseItem *parent)
|
||||
: ConnectableItem(pos, parent)
|
||||
{
|
||||
setItemBoundingRect(QRectF(-20, -20, 40, 40));
|
||||
setMinimumHeight(40);
|
||||
setMinimumWidth(40);
|
||||
|
||||
m_pen.setColor(qRgb(0x12, 0x12, 0x12));
|
||||
m_pen.setWidth(2);
|
||||
}
|
||||
|
||||
void FinalStateItem::updatePolygon()
|
||||
{
|
||||
QRectF r = boundingRect();
|
||||
m_size = qMin(r.width() * 0.45, r.height() * 0.45);
|
||||
QPointF center = r.center();
|
||||
|
||||
m_polygon.clear();
|
||||
m_polygon << (center + QPointF(-m_size, -m_size))
|
||||
<< (center + QPointF(m_size, -m_size))
|
||||
<< (center + QPointF(m_size, m_size))
|
||||
<< (center + QPointF(-m_size, m_size))
|
||||
<< (center + QPointF(-m_size, -m_size));
|
||||
}
|
||||
|
||||
void FinalStateItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
ConnectableItem::paint(painter, option, widget);
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setOpacity(getOpacity());
|
||||
|
||||
painter->setBrush(QColor(0xff, 0xff, 0xff));
|
||||
m_pen.setColor(overlapping() ? qRgb(0xff, 0x00, 0x60) : qRgb(0x45, 0x45, 0x45));
|
||||
painter->setPen(m_pen);
|
||||
painter->drawEllipse(boundingRect().center(), m_size, m_size);
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(QColor(0x4d, 0x4d, 0x4d));
|
||||
painter->drawEllipse(boundingRect().center(), m_size * 0.8, m_size * 0.8);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
bool FinalStateItem::canStartTransition(ItemType type) const
|
||||
{
|
||||
Q_UNUSED(type)
|
||||
return false;
|
||||
}
|
||||
61
src/plugins/scxmleditor/plugin_interface/finalstateitem.h
Normal file
61
src/plugins/scxmleditor/plugin_interface/finalstateitem.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "connectableitem.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The FinalStateItem class represents Final-state of the SCXML-standard. It is a extended class from the ConnectableItem.
|
||||
*/
|
||||
class FinalStateItem : public ConnectableItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FinalStateItem(const QPointF &pos = QPointF(), BaseItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return FinalStateType;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
protected:
|
||||
void updatePolygon() override;
|
||||
bool canStartTransition(ItemType type) const override;
|
||||
|
||||
private:
|
||||
qreal m_size;
|
||||
QPen m_pen;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "genericscxmlplugin.h"
|
||||
#include "mytypes.h"
|
||||
#include "scattributeitemdelegate.h"
|
||||
#include "scattributeitemmodel.h"
|
||||
#include "scgraphicsitemprovider.h"
|
||||
#include "scshapeprovider.h"
|
||||
#include "scutilsprovider.h"
|
||||
#include "scxmluifactory.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
GenericScxmlPlugin::GenericScxmlPlugin(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
GenericScxmlPlugin::~GenericScxmlPlugin()
|
||||
{
|
||||
delete m_attributeItemDelegate;
|
||||
delete m_attributeItemModel;
|
||||
delete m_graphicsItemProvider;
|
||||
delete m_shapeProvider;
|
||||
delete m_utilsProvider;
|
||||
}
|
||||
|
||||
void GenericScxmlPlugin::documentChanged(DocumentChangeType type, ScxmlDocument *doc)
|
||||
{
|
||||
Q_UNUSED(type)
|
||||
Q_UNUSED(doc)
|
||||
}
|
||||
|
||||
void GenericScxmlPlugin::detach()
|
||||
{
|
||||
m_factory->unregisterObject("attributeItemDelegate", m_attributeItemDelegate);
|
||||
m_factory->unregisterObject("attributeItemModel", m_attributeItemModel);
|
||||
m_factory->unregisterObject("graphicsItemProvider", m_graphicsItemProvider);
|
||||
m_factory->unregisterObject("shapeProvider", m_shapeProvider);
|
||||
m_factory->unregisterObject("utilsProvider", m_utilsProvider);
|
||||
}
|
||||
|
||||
void GenericScxmlPlugin::init(ScxmlUiFactory *factory)
|
||||
{
|
||||
m_factory = factory;
|
||||
|
||||
m_attributeItemDelegate = new SCAttributeItemDelegate;
|
||||
m_attributeItemModel = new SCAttributeItemModel;
|
||||
m_graphicsItemProvider = new SCGraphicsItemProvider;
|
||||
m_shapeProvider = new SCShapeProvider;
|
||||
m_utilsProvider = new SCUtilsProvider;
|
||||
|
||||
m_factory->registerObject("attributeItemDelegate", m_attributeItemDelegate);
|
||||
m_factory->registerObject("attributeItemModel", m_attributeItemModel);
|
||||
m_factory->registerObject("graphicsItemProvider", m_graphicsItemProvider);
|
||||
m_factory->registerObject("shapeProvider", m_shapeProvider);
|
||||
m_factory->registerObject("utilsProvider", m_utilsProvider);
|
||||
}
|
||||
|
||||
void GenericScxmlPlugin::refresh()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "isceditor.h"
|
||||
#include "mytypes.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlUiFactory;
|
||||
class SCAttributeItemDelegate;
|
||||
class SCAttributeItemModel;
|
||||
class ScxmlDocument;
|
||||
class SCGraphicsItemProvider;
|
||||
class SCShapeProvider;
|
||||
class SCUtilsProvider;
|
||||
|
||||
class GenericScxmlPlugin : public QObject, public ISCEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(ScxmlEditor::PluginInterface::ISCEditor)
|
||||
|
||||
public:
|
||||
GenericScxmlPlugin(QObject *parent = nullptr);
|
||||
~GenericScxmlPlugin() override;
|
||||
|
||||
void init(ScxmlUiFactory *factory) override;
|
||||
void detach() override;
|
||||
void documentChanged(DocumentChangeType type, ScxmlDocument *doc) override;
|
||||
void refresh() override;
|
||||
|
||||
private:
|
||||
ScxmlUiFactory *m_factory = nullptr;
|
||||
SCAttributeItemDelegate *m_attributeItemDelegate = nullptr;
|
||||
SCAttributeItemModel *m_attributeItemModel = nullptr;
|
||||
SCGraphicsItemProvider *m_graphicsItemProvider = nullptr;
|
||||
SCShapeProvider *m_shapeProvider = nullptr;
|
||||
SCUtilsProvider *m_utilsProvider = nullptr;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class BaseItem;
|
||||
class WarningItem;
|
||||
|
||||
class GraphicsItemProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GraphicsItemProvider(QObject *parent = nullptr)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual WarningItem *createWarningItem(const QString &key, BaseItem *parentItem) const = 0;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
944
src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
Normal file
944
src/plugins/scxmleditor/plugin_interface/graphicsscene.cpp
Normal file
@@ -0,0 +1,944 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "graphicsscene.h"
|
||||
#include "actionhandler.h"
|
||||
#include "actionprovider.h"
|
||||
#include "finalstateitem.h"
|
||||
#include "initialstateitem.h"
|
||||
#include "parallelitem.h"
|
||||
#include "sceneutils.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "scxmltagutils.h"
|
||||
#include "scxmluifactory.h"
|
||||
#include "snapline.h"
|
||||
#include "stateitem.h"
|
||||
#include "transitionitem.h"
|
||||
#include "utilsprovider.h"
|
||||
#include "warning.h"
|
||||
#include "warningitem.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QGuiApplication>
|
||||
#include <QClipboard>
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
#include <QThread>
|
||||
#include <QUndoStack>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
GraphicsScene::GraphicsScene(QObject *parent)
|
||||
: QGraphicsScene(parent)
|
||||
{
|
||||
//setMinimumRenderSize(5);
|
||||
setItemIndexMethod(QGraphicsScene::NoIndex);
|
||||
}
|
||||
|
||||
GraphicsScene::~GraphicsScene()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void GraphicsScene::unselectAll()
|
||||
{
|
||||
const QList<QGraphicsItem*> selectedItems = this->selectedItems();
|
||||
foreach (QGraphicsItem *it, selectedItems)
|
||||
it->setSelected(false);
|
||||
if (m_document)
|
||||
m_document->setCurrentTag(0);
|
||||
}
|
||||
|
||||
void GraphicsScene::unhighlightAll()
|
||||
{
|
||||
foreach (BaseItem *it, m_baseItems)
|
||||
it->setHighlight(false);
|
||||
}
|
||||
|
||||
void GraphicsScene::highlightItems(const QVector<ScxmlTag*> &lstIds)
|
||||
{
|
||||
foreach (BaseItem *it, m_baseItems)
|
||||
it->setHighlight(lstIds.contains(it->tag()));
|
||||
}
|
||||
|
||||
QRectF GraphicsScene::selectedBoundingRect() const
|
||||
{
|
||||
QRectF r;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected())
|
||||
r = r.united(item->sceneBoundingRect());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
qreal GraphicsScene::selectedMaxWidth() const
|
||||
{
|
||||
qreal maxw = 0;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
maxw = qMax(maxw, item->sceneBoundingRect().width());
|
||||
}
|
||||
return maxw;
|
||||
}
|
||||
|
||||
qreal GraphicsScene::selectedMaxHeight() const
|
||||
{
|
||||
qreal maxh = 0;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
maxh = qMax(maxh, item->sceneBoundingRect().height());
|
||||
}
|
||||
return maxh;
|
||||
}
|
||||
|
||||
void GraphicsScene::alignStates(int alignType)
|
||||
{
|
||||
if (alignType >= ActionAlignLeft && alignType <= ActionAlignVertical) {
|
||||
m_document->undoStack()->beginMacro(tr("Align states"));
|
||||
QRectF r = selectedBoundingRect();
|
||||
|
||||
if (r.isValid()) {
|
||||
switch (alignType) {
|
||||
case ActionAlignLeft:
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
item->moveStateBy(r.left() - item->sceneBoundingRect().left(), 0);
|
||||
}
|
||||
break;
|
||||
case ActionAlignRight:
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
item->moveStateBy(r.right() - item->sceneBoundingRect().right(), 0);
|
||||
}
|
||||
break;
|
||||
case ActionAlignTop:
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
item->moveStateBy(0, r.top() - item->sceneBoundingRect().top());
|
||||
}
|
||||
break;
|
||||
case ActionAlignBottom:
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
item->moveStateBy(0, r.bottom() - item->sceneBoundingRect().bottom());
|
||||
}
|
||||
break;
|
||||
case ActionAlignHorizontal:
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
item->moveStateBy(0, r.center().y() - item->sceneBoundingRect().center().y());
|
||||
}
|
||||
break;
|
||||
case ActionAlignVertical:
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType)
|
||||
item->moveStateBy(r.center().x() - item->sceneBoundingRect().center().x(), 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_document->undoStack()->endMacro();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::adjustStates(int adjustType)
|
||||
{
|
||||
if (adjustType >= ActionAdjustWidth && adjustType <= ActionAdjustSize) {
|
||||
m_document->undoStack()->beginMacro(tr("Adjust states"));
|
||||
qreal maxw = selectedMaxWidth();
|
||||
qreal maxh = selectedMaxHeight();
|
||||
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= InitialStateType) {
|
||||
QRectF rr = item->boundingRect();
|
||||
if ((adjustType == ActionAdjustWidth || adjustType == ActionAdjustSize) && !qFuzzyCompare(rr.width(), maxw))
|
||||
rr.setWidth(maxw);
|
||||
if ((adjustType == ActionAdjustHeight || adjustType == ActionAdjustSize) && !qFuzzyCompare(rr.height(), maxh))
|
||||
rr.setHeight(maxh);
|
||||
|
||||
item->setItemBoundingRect(rr);
|
||||
qgraphicsitem_cast<ConnectableItem*>(item)->updateTransitions(true);
|
||||
}
|
||||
}
|
||||
m_document->undoStack()->endMacro();
|
||||
}
|
||||
}
|
||||
void GraphicsScene::cut()
|
||||
{
|
||||
m_document->undoStack()->beginMacro(tr("Cut"));
|
||||
copy();
|
||||
removeSelectedItems();
|
||||
m_document->undoStack()->endMacro();
|
||||
}
|
||||
|
||||
void GraphicsScene::removeSelectedItems()
|
||||
{
|
||||
QVector<ScxmlTag*> tags = SceneUtils::findRemovedTags(m_baseItems);
|
||||
if (tags.count() > 0) {
|
||||
m_document->undoStack()->beginMacro(tr("Remove item(s)"));
|
||||
|
||||
// Then remove found tags
|
||||
for (int i = tags.count(); i--;) {
|
||||
m_document->setCurrentTag(tags[i]);
|
||||
m_document->removeTag(tags[i]);
|
||||
}
|
||||
m_document->setCurrentTag(0);
|
||||
m_document->undoStack()->endMacro();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::copy()
|
||||
{
|
||||
QPointF minPos;
|
||||
QVector<ScxmlTag*> tags;
|
||||
if (m_document->currentTag()->tagType() == Scxml) {
|
||||
QVector<BaseItem*> items;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (!item->parentItem())
|
||||
items << item;
|
||||
}
|
||||
tags = SceneUtils::findCopyTags(items, minPos);
|
||||
} else {
|
||||
tags = SceneUtils::findCopyTags(m_baseItems, minPos);
|
||||
}
|
||||
|
||||
if (tags.isEmpty() && m_document->currentTag())
|
||||
tags << m_document->currentTag();
|
||||
|
||||
if (tags.count() > 0) {
|
||||
auto mime = new QMimeData;
|
||||
QByteArray result = m_document->content(tags);
|
||||
mime->setText(QLatin1String(result));
|
||||
mime->setData("StateChartEditor/StateData", result);
|
||||
QStringList strTypes;
|
||||
foreach (const ScxmlTag *tag, tags) {
|
||||
strTypes << tag->tagName(false);
|
||||
}
|
||||
mime->setData("StateChartEditor/CopiedTagTypes", strTypes.join(",").toLocal8Bit());
|
||||
mime->setData("StateChartEditor/CopiedMinPos", QString::fromLatin1("%1:%2").arg(minPos.x()).arg(minPos.y()).toLocal8Bit());
|
||||
QGuiApplication::clipboard()->setMimeData(mime);
|
||||
}
|
||||
|
||||
checkPaste();
|
||||
}
|
||||
|
||||
void GraphicsScene::checkPaste()
|
||||
{
|
||||
const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData();
|
||||
const QString copiedTagTypes = QLatin1String(mimeData->data("StateChartEditor/CopiedTagTypes"));
|
||||
|
||||
emit pasteAvailable(TagUtils::checkPaste(copiedTagTypes, m_document->currentTag()));
|
||||
}
|
||||
|
||||
void GraphicsScene::paste(const QPointF &targetPos)
|
||||
{
|
||||
const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData();
|
||||
|
||||
QPointF startPos(targetPos);
|
||||
|
||||
BaseItem *targetItem = nullptr;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= StateType) {
|
||||
targetItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_lastPasteTargetItem != targetItem)
|
||||
m_pasteCounter = 0;
|
||||
m_lastPasteTargetItem = targetItem;
|
||||
|
||||
if (m_lastPasteTargetItem)
|
||||
startPos = m_lastPasteTargetItem->boundingRect().topLeft();
|
||||
QPointF pastedPos = startPos + QPointF(m_pasteCounter * 30, m_pasteCounter * 30);
|
||||
m_pasteCounter++;
|
||||
|
||||
QString strMinPos = QLatin1String(mimeData->data("StateChartEditor/CopiedMinPos"));
|
||||
QPointF minPos(0, 0);
|
||||
if (!strMinPos.isEmpty()) {
|
||||
QStringList coords = strMinPos.split(":", QString::SkipEmptyParts);
|
||||
if (coords.count() == 2)
|
||||
minPos = QPointF(coords[0].toDouble(), coords[1].toDouble());
|
||||
}
|
||||
|
||||
m_document->pasteData(mimeData->data("StateChartEditor/StateData"), minPos, pastedPos);
|
||||
}
|
||||
|
||||
void GraphicsScene::setEditorInfo(const QString &key, const QString &value)
|
||||
{
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected() && item->type() >= TransitionType)
|
||||
item->setEditorInfo(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::setDocument(ScxmlDocument *document)
|
||||
{
|
||||
if (m_document)
|
||||
disconnect(m_document, 0, this, 0);
|
||||
|
||||
m_document = document;
|
||||
|
||||
init();
|
||||
connectDocument();
|
||||
}
|
||||
|
||||
void GraphicsScene::connectDocument()
|
||||
{
|
||||
if (m_document) {
|
||||
connect(m_document, &ScxmlDocument::beginTagChange, this, &GraphicsScene::beginTagChange);
|
||||
connect(m_document, &ScxmlDocument::endTagChange, this, &GraphicsScene::endTagChange);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::disconnectDocument()
|
||||
{
|
||||
if (m_document)
|
||||
m_document->disconnect(this);
|
||||
}
|
||||
|
||||
void GraphicsScene::init()
|
||||
{
|
||||
m_initializing = true;
|
||||
|
||||
disconnectDocument();
|
||||
clear();
|
||||
addItem(m_lineX = new SnapLine);
|
||||
addItem(m_lineY = new SnapLine);
|
||||
|
||||
if (m_document) {
|
||||
const ScxmlTag *rootTag = m_document->rootTag();
|
||||
if (rootTag) {
|
||||
|
||||
for (int i = 0; i < rootTag->childCount(); ++i) {
|
||||
ScxmlTag *child = rootTag->child(i);
|
||||
ConnectableItem *newItem = SceneUtils::createItemByTagType(child->tagType());
|
||||
if (newItem) {
|
||||
addItem(newItem);
|
||||
newItem->init(child);
|
||||
}
|
||||
}
|
||||
|
||||
const QList<QGraphicsItem*> items = this->items();
|
||||
for (int i = 0; i < items.count(); ++i) {
|
||||
if (items[i]->type() >= TransitionType) {
|
||||
auto item = qgraphicsitem_cast<BaseItem*>(items[i]);
|
||||
if (item)
|
||||
item->finalizeCreation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_initializing = false;
|
||||
warningVisibilityChanged(0, 0);
|
||||
emit selectedStateCountChanged(0);
|
||||
emit selectedBaseItemCountChanged(0);
|
||||
}
|
||||
|
||||
void GraphicsScene::runLayoutToSelectedStates()
|
||||
{
|
||||
m_document->undoStack()->beginMacro(tr("Relayout"));
|
||||
|
||||
QVector<BaseItem*> selectedItems;
|
||||
foreach (BaseItem *node, m_baseItems) {
|
||||
if (node->isSelected()) {
|
||||
int index = 0;
|
||||
for (int i = 0; i < selectedItems.count(); ++i) {
|
||||
if (node->depth() <= selectedItems[i]->depth()) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
selectedItems.insert(index, node);
|
||||
}
|
||||
}
|
||||
|
||||
// Layout selected items
|
||||
for (int i = 0; i < selectedItems.count(); ++i)
|
||||
selectedItems[i]->doLayout(selectedItems[i]->depth());
|
||||
|
||||
// Layout scene items if necessary
|
||||
if (selectedItems.isEmpty()) {
|
||||
QList<QGraphicsItem*> sceneItems;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->type() >= InitialStateType && !item->parentItem())
|
||||
sceneItems << item;
|
||||
}
|
||||
SceneUtils::layout(sceneItems);
|
||||
|
||||
foreach (QGraphicsItem *item, sceneItems) {
|
||||
if (item->type() >= StateType)
|
||||
static_cast<StateItem*>(item)->shrink();
|
||||
}
|
||||
}
|
||||
|
||||
// Update properties
|
||||
foreach (BaseItem *node, selectedItems) {
|
||||
node->updateUIProperties();
|
||||
}
|
||||
|
||||
m_document->undoStack()->endMacro();
|
||||
}
|
||||
|
||||
void GraphicsScene::runAutomaticLayout()
|
||||
{
|
||||
m_autoLayoutRunning = true;
|
||||
|
||||
// 1. Find max depth
|
||||
int maxDepth = 0;
|
||||
foreach (BaseItem *node, m_baseItems) {
|
||||
maxDepth = qMax(maxDepth, node->depth());
|
||||
node->setBlockUpdates(true);
|
||||
}
|
||||
|
||||
// 2. Layout every depth-level separately
|
||||
for (int d = (maxDepth + 1); d--;) {
|
||||
foreach (BaseItem *node, m_baseItems)
|
||||
node->doLayout(d);
|
||||
}
|
||||
|
||||
// 3. Layout scene items
|
||||
QList<QGraphicsItem*> sceneItems;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->type() >= InitialStateType && !item->parentItem())
|
||||
sceneItems << item;
|
||||
}
|
||||
SceneUtils::layout(sceneItems);
|
||||
|
||||
foreach (QGraphicsItem *item, sceneItems) {
|
||||
if (item->type() >= StateType)
|
||||
static_cast<StateItem*>(item)->shrink();
|
||||
}
|
||||
|
||||
foreach (BaseItem *node, m_baseItems) {
|
||||
node->updateUIProperties();
|
||||
node->setBlockUpdates(false);
|
||||
}
|
||||
|
||||
m_autoLayoutRunning = false;
|
||||
}
|
||||
|
||||
void GraphicsScene::beginTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag, const QVariant &value)
|
||||
{
|
||||
switch (change) {
|
||||
case ScxmlDocument::TagRemoveChild: {
|
||||
if (tag)
|
||||
removeItems(tag->child(value.toInt()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::endTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag, const QVariant &value)
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
QTC_ASSERT(tag, return);
|
||||
|
||||
switch (change) {
|
||||
case ScxmlDocument::TagAttributesChanged: {
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->tag() == tag)
|
||||
item->updateAttributes();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ScxmlDocument::TagEditorInfoChanged: {
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->tag() == tag)
|
||||
item->updateEditorInfo();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ScxmlDocument::TagCurrentChanged: {
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (!item->isSelected() && item->tag() == tag)
|
||||
item->setSelected(true);
|
||||
}
|
||||
checkPaste();
|
||||
break;
|
||||
}
|
||||
case ScxmlDocument::TagChangeParent: {
|
||||
auto childItem = qobject_cast<ConnectableItem*>(findItem(tag));
|
||||
|
||||
if (childItem) {
|
||||
BaseItem *newParentItem = findItem(tag->parentTag());
|
||||
BaseItem *oldParentItem = childItem ? childItem->parentBaseItem() : nullptr;
|
||||
|
||||
QPointF sPos = childItem->scenePos();
|
||||
if (oldParentItem) {
|
||||
childItem->setParentItem(nullptr);
|
||||
childItem->setPos(sPos);
|
||||
}
|
||||
|
||||
if (newParentItem)
|
||||
childItem->setPos(newParentItem->mapFromScene(childItem->sceneBoundingRect().center()) - childItem->boundingRect().center());
|
||||
|
||||
childItem->setParentItem(newParentItem);
|
||||
childItem->updateUIProperties();
|
||||
childItem->updateTransitions(true);
|
||||
childItem->updateTransitionAttributes(true);
|
||||
childItem->checkWarnings();
|
||||
childItem->checkInitial();
|
||||
if (newParentItem) {
|
||||
newParentItem->checkInitial();
|
||||
newParentItem->updateAttributes();
|
||||
newParentItem->checkWarnings();
|
||||
newParentItem->checkOverlapping();
|
||||
newParentItem->updateUIProperties();
|
||||
}
|
||||
|
||||
if (oldParentItem)
|
||||
oldParentItem->checkInitial();
|
||||
|
||||
if (oldParentItem == nullptr || newParentItem == nullptr)
|
||||
checkInitialState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ScxmlDocument::TagAddTags: {
|
||||
// Finalize transitions
|
||||
QVector<ScxmlTag*> childTransitionTags;
|
||||
if (tag->tagName(false) == "transition")
|
||||
childTransitionTags << tag;
|
||||
|
||||
TagUtils::findAllTransitionChildren(tag, childTransitionTags);
|
||||
for (int i = 0; i < childTransitionTags.count(); ++i) {
|
||||
BaseItem *item = findItem(childTransitionTags[i]);
|
||||
if (item)
|
||||
item->finalizeCreation();
|
||||
}
|
||||
}
|
||||
// FIXME: intended fallthrough?
|
||||
case ScxmlDocument::TagAddChild: {
|
||||
ScxmlTag *childTag = tag->child(value.toInt());
|
||||
if (childTag) {
|
||||
// Check that there is no any item with this tag
|
||||
BaseItem *childItem = findItem(childTag);
|
||||
BaseItem *parentItem = findItem(tag);
|
||||
if (!childItem) {
|
||||
if (childTag->tagType() == Transition || childTag->tagType() == InitialTransition) {
|
||||
auto transition = new TransitionItem;
|
||||
addItem(transition);
|
||||
transition->setStartItem(qgraphicsitem_cast<ConnectableItem*>(parentItem));
|
||||
transition->init(childTag, 0, false, false);
|
||||
transition->updateAttributes();
|
||||
} else {
|
||||
childItem = SceneUtils::createItemByTagType(childTag->tagType(), QPointF());
|
||||
if (childItem) {
|
||||
childItem->init(childTag, parentItem, false);
|
||||
if (!parentItem)
|
||||
addItem(childItem);
|
||||
|
||||
childItem->finalizeCreation();
|
||||
childItem->updateUIProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parentItem) {
|
||||
parentItem->updateAttributes();
|
||||
parentItem->updateUIProperties();
|
||||
parentItem->checkInitial();
|
||||
} else
|
||||
checkInitialState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ScxmlDocument::TagRemoveChild: {
|
||||
BaseItem *parentItem = findItem(tag);
|
||||
if (parentItem) {
|
||||
parentItem->updateAttributes();
|
||||
parentItem->checkInitial();
|
||||
} else {
|
||||
checkInitialState();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ScxmlDocument::TagChangeOrder: {
|
||||
BaseItem *parentItem = findItem(tag->parentTag());
|
||||
if (parentItem)
|
||||
parentItem->updateAttributes();
|
||||
else
|
||||
checkInitialState();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::setTopMostScene(bool topmost)
|
||||
{
|
||||
m_topMostScene = topmost;
|
||||
}
|
||||
|
||||
bool GraphicsScene::topMostScene() const
|
||||
{
|
||||
return m_topMostScene;
|
||||
}
|
||||
|
||||
void GraphicsScene::setActionHandler(ActionHandler *mgr)
|
||||
{
|
||||
m_actionHandler = mgr;
|
||||
}
|
||||
|
||||
void GraphicsScene::setWarningModel(ScxmlEditor::OutputPane::WarningModel *model)
|
||||
{
|
||||
m_warningModel = model;
|
||||
}
|
||||
|
||||
void GraphicsScene::setUiFactory(ScxmlUiFactory *uifactory)
|
||||
{
|
||||
m_uiFactory = uifactory;
|
||||
}
|
||||
|
||||
ActionHandler *GraphicsScene::actionHandler() const
|
||||
{
|
||||
return m_actionHandler;
|
||||
}
|
||||
|
||||
ScxmlEditor::OutputPane::WarningModel *GraphicsScene::warningModel() const
|
||||
{
|
||||
return m_warningModel;
|
||||
}
|
||||
|
||||
ScxmlUiFactory *GraphicsScene::uiFactory() const
|
||||
{
|
||||
return m_uiFactory;
|
||||
}
|
||||
|
||||
void GraphicsScene::addConnectableItem(ItemType type, const QPointF &pos, BaseItem *parentItem)
|
||||
{
|
||||
m_document->undoStack()->beginMacro(tr("Add new state"));
|
||||
ConnectableItem *newItem = SceneUtils::createItem(type, pos);
|
||||
|
||||
if (newItem) {
|
||||
ScxmlTag *newTag = SceneUtils::createTag(type, m_document);
|
||||
ScxmlTag *parentTag = parentItem ? parentItem->tag() : m_document->rootTag();
|
||||
|
||||
newItem->setTag(newTag);
|
||||
newItem->setParentItem(parentItem);
|
||||
if (!parentItem)
|
||||
addItem(newItem);
|
||||
|
||||
newItem->updateAttributes();
|
||||
newItem->updateEditorInfo();
|
||||
newItem->updateUIProperties();
|
||||
|
||||
if (parentItem)
|
||||
parentItem->updateUIProperties();
|
||||
|
||||
m_document->addTag(parentTag, newTag);
|
||||
unselectAll();
|
||||
newItem->setSelected(true);
|
||||
}
|
||||
m_document->undoStack()->endMacro();
|
||||
}
|
||||
|
||||
void GraphicsScene::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
QGraphicsItem *focusItem = this->focusItem();
|
||||
if (focusItem == nullptr || focusItem->type() != TextType) {
|
||||
if (event->key() == Qt::Key_Delete)
|
||||
removeSelectedItems();
|
||||
}
|
||||
QGraphicsScene::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
QGraphicsItem *it = itemAt(event->scenePos(), QTransform());
|
||||
if (it == nullptr || it->type() == LayoutType) {
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
QGraphicsScene::mousePressEvent(event);
|
||||
m_document->setCurrentTag(m_document->rootTag());
|
||||
return;
|
||||
} else if (m_actionHandler && event->button() == Qt::RightButton) {
|
||||
event->accept();
|
||||
QMenu menu;
|
||||
menu.addAction(m_actionHandler->action(ActionCopy));
|
||||
menu.addAction(m_actionHandler->action(ActionPaste));
|
||||
menu.addAction(m_actionHandler->action(ActionScreenshot));
|
||||
menu.addAction(m_actionHandler->action(ActionExportToImage));
|
||||
menu.addSeparator();
|
||||
menu.addAction(m_actionHandler->action(ActionZoomIn));
|
||||
menu.addAction(m_actionHandler->action(ActionZoomOut));
|
||||
menu.addAction(m_actionHandler->action(ActionFitToView));
|
||||
|
||||
if (m_uiFactory) {
|
||||
auto actionProvider = static_cast<ActionProvider*>(m_uiFactory->object(Constants::C_UI_FACTORY_OBJECT_ACTIONPROVIDER));
|
||||
if (actionProvider) {
|
||||
menu.addSeparator();
|
||||
actionProvider->initStateMenu(m_document->rootTag(), &menu);
|
||||
}
|
||||
}
|
||||
|
||||
menu.exec(event->screenPos());
|
||||
return;
|
||||
}
|
||||
}
|
||||
QGraphicsScene::mousePressEvent(event);
|
||||
}
|
||||
|
||||
BaseItem *GraphicsScene::findItem(const ScxmlTag *tag) const
|
||||
{
|
||||
if (!tag)
|
||||
return nullptr;
|
||||
|
||||
foreach (BaseItem *it, m_baseItems) {
|
||||
if (it->tag() == tag)
|
||||
return it;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GraphicsScene::removeItems(const ScxmlTag *tag)
|
||||
{
|
||||
if (tag) {
|
||||
// Find right items
|
||||
QVector<BaseItem*> items;
|
||||
foreach (BaseItem *it, m_baseItems) {
|
||||
if (it->tag() == tag)
|
||||
items << it;
|
||||
}
|
||||
|
||||
// Then delete them
|
||||
for (int i = items.count(); i--;) {
|
||||
items[i]->setTag(0);
|
||||
delete items[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPair<bool, bool> GraphicsScene::checkSnapToItem(BaseItem *item, const QPointF &p, QPointF &pp)
|
||||
{
|
||||
if (m_selectedStateCount > 1)
|
||||
return QPair<bool, bool>(false, false);
|
||||
|
||||
QGraphicsItem *parentItem = item->parentItem();
|
||||
|
||||
qreal diffX = 8;
|
||||
qreal diffXdY = 2000;
|
||||
|
||||
qreal diffY = 8;
|
||||
qreal diffYdX = 2000;
|
||||
|
||||
foreach (BaseItem *it, m_baseItems) {
|
||||
if (!it->isSelected() && it != item && it->parentItem() == parentItem && it->type() >= InitialStateType) {
|
||||
QPointF c = it->sceneCenter();
|
||||
qreal dX = qAbs(c.x() - p.x());
|
||||
qreal dY = qAbs(c.y() - p.y());
|
||||
|
||||
if (dX < 7 && dY < diffXdY) {
|
||||
pp.setX(c.x());
|
||||
diffX = dX;
|
||||
diffXdY = dY;
|
||||
m_lineY->show(c.x(), c.y(), c.x(), p.y());
|
||||
}
|
||||
|
||||
if (dY < 7 && dX < diffYdX) {
|
||||
pp.setY(c.y());
|
||||
diffY = dY;
|
||||
diffYdX = dX;
|
||||
m_lineX->show(c.x(), c.y(), p.x(), c.y());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (qFuzzyCompare(diffX, 8))
|
||||
m_lineY->hideLine();
|
||||
if (qFuzzyCompare(diffY, 8))
|
||||
m_lineX->hideLine();
|
||||
|
||||
return QPair<bool, bool>(diffX < 8, diffY < 8);
|
||||
}
|
||||
|
||||
void GraphicsScene::selectionChanged(bool para)
|
||||
{
|
||||
Q_UNUSED(para)
|
||||
|
||||
int count = 0;
|
||||
int baseCount = 0;
|
||||
int stateTypeCount = 0;
|
||||
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->isSelected()) {
|
||||
if (item->type() >= TransitionType)
|
||||
baseCount++;
|
||||
if (item->type() >= InitialStateType)
|
||||
count++;
|
||||
if (item->type() >= StateType)
|
||||
stateTypeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
m_selectedStateTypeCount = stateTypeCount;
|
||||
|
||||
if (count != m_selectedStateCount) {
|
||||
m_selectedStateCount = count;
|
||||
emit selectedStateCountChanged(m_selectedStateCount);
|
||||
}
|
||||
|
||||
if (baseCount != m_selectedBaseItemCount) {
|
||||
m_selectedBaseItemCount = baseCount;
|
||||
emit selectedBaseItemCountChanged(m_selectedBaseItemCount);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::addWarningItem(WarningItem *item)
|
||||
{
|
||||
if (!m_allWarnings.contains(item)) {
|
||||
m_allWarnings << item;
|
||||
if (!m_autoLayoutRunning && !m_initializing)
|
||||
QMetaObject::invokeMethod(this, "warningVisibilityChanged", Qt::QueuedConnection, Q_ARG(int, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::removeWarningItem(WarningItem *item)
|
||||
{
|
||||
m_allWarnings.removeAll(item);
|
||||
|
||||
if (!m_autoLayoutRunning && !m_initializing)
|
||||
QMetaObject::invokeMethod(this, "warningVisibilityChanged", Qt::QueuedConnection, Q_ARG(int, 0));
|
||||
}
|
||||
|
||||
void GraphicsScene::warningVisibilityChanged(int type, WarningItem *item)
|
||||
{
|
||||
if (!m_autoLayoutRunning && !m_initializing) {
|
||||
foreach (WarningItem *it, m_allWarnings) {
|
||||
if (it != item && (type == 0 || it->type() == type))
|
||||
it->check();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScxmlTag *GraphicsScene::tagByWarning(const ScxmlEditor::OutputPane::Warning *w) const
|
||||
{
|
||||
ScxmlTag *tag = nullptr;
|
||||
foreach (WarningItem *it, m_allWarnings) {
|
||||
if (it->warning() == w) {
|
||||
tag = it->tag();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
void GraphicsScene::highlightWarningItem(const ScxmlEditor::OutputPane::Warning *w)
|
||||
{
|
||||
ScxmlTag *tag = tagByWarning(w);
|
||||
|
||||
if (tag)
|
||||
highlightItems(QVector<ScxmlTag*>() << tag);
|
||||
else
|
||||
unhighlightAll();
|
||||
}
|
||||
|
||||
void GraphicsScene::selectWarningItem(const ScxmlEditor::OutputPane::Warning *w)
|
||||
{
|
||||
ScxmlTag *tag = tagByWarning(w);
|
||||
|
||||
if (tag) {
|
||||
unselectAll();
|
||||
m_document->setCurrentTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
QList<QGraphicsItem*> GraphicsScene::sceneItems(Qt::SortOrder order) const
|
||||
{
|
||||
QList<QGraphicsItem*> children;
|
||||
QList<QGraphicsItem*> items = this->items(order);
|
||||
for (int i = 0; i < items.count(); ++i) {
|
||||
if (items[i]->parentItem() == nullptr && items[i]->type() >= InitialStateType)
|
||||
children << items[i];
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
void GraphicsScene::addChild(BaseItem *item)
|
||||
{
|
||||
if (!m_baseItems.contains(item)) {
|
||||
connect(item, &BaseItem::selectedStateChanged, this, &GraphicsScene::selectionChanged);
|
||||
connect(item, &BaseItem::openToDifferentView, this, [=](BaseItem *item){
|
||||
openStateView(item);
|
||||
}, Qt::QueuedConnection);
|
||||
m_baseItems << item;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::removeChild(BaseItem *item)
|
||||
{
|
||||
if (item)
|
||||
disconnect(item, 0, this, 0);
|
||||
m_baseItems.removeAll(item);
|
||||
|
||||
selectionChanged(false);
|
||||
}
|
||||
|
||||
void GraphicsScene::checkItemsVisibility(double scaleFactor)
|
||||
{
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
item->checkVisibility(scaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::checkInitialState()
|
||||
{
|
||||
if (m_document) {
|
||||
QList<QGraphicsItem*> sceneItems;
|
||||
foreach (BaseItem *item, m_baseItems) {
|
||||
if (item->type() >= InitialStateType && !item->parentItem())
|
||||
sceneItems << item;
|
||||
}
|
||||
if (m_uiFactory) {
|
||||
auto utilsProvider = static_cast<UtilsProvider*>(m_uiFactory->object("utilsProvider"));
|
||||
if (utilsProvider)
|
||||
utilsProvider->checkInitialState(sceneItems, m_document->rootTag());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::clearAllTags()
|
||||
{
|
||||
foreach (BaseItem *it, m_baseItems) {
|
||||
it->setTag(0);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsScene::setBlockUpdates(bool block)
|
||||
{
|
||||
foreach (BaseItem *it, m_baseItems) {
|
||||
it->setBlockUpdates(block);
|
||||
}
|
||||
}
|
||||
152
src/plugins/scxmleditor/plugin_interface/graphicsscene.h
Normal file
152
src/plugins/scxmleditor/plugin_interface/graphicsscene.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
#include "scxmldocument.h"
|
||||
|
||||
#include <QGraphicsLineItem>
|
||||
#include <QGraphicsScene>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QAction)
|
||||
QT_FORWARD_DECLARE_CLASS(QKeyEvent)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace OutputPane {
|
||||
class Warning;
|
||||
class WarningModel;
|
||||
} // namespace OutputPane
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ActionHandler;
|
||||
class ScxmlUiFactory;
|
||||
class SnapLine;
|
||||
class WarningItem;
|
||||
|
||||
class GraphicsScene : public QGraphicsScene
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GraphicsScene(QObject *parent = nullptr);
|
||||
~GraphicsScene() override;
|
||||
|
||||
QPair<bool, bool> checkSnapToItem(BaseItem *item, const QPointF &p, QPointF &pp);
|
||||
void checkItemsVisibility(double scaleFactor);
|
||||
void checkInitialState();
|
||||
void clearAllTags();
|
||||
void setBlockUpdates(bool block);
|
||||
|
||||
QList<QGraphicsItem*> sceneItems(Qt::SortOrder order) const;
|
||||
ScxmlTag *tagByWarning(const OutputPane::Warning *w) const;
|
||||
void highlightWarningItem(const OutputPane::Warning *w);
|
||||
void selectWarningItem(const OutputPane::Warning *w);
|
||||
|
||||
QRectF selectedBoundingRect() const;
|
||||
BaseItem *findItem(const ScxmlTag *tag) const;
|
||||
bool topMostScene() const;
|
||||
|
||||
void setActionHandler(ActionHandler *mgr);
|
||||
void setWarningModel(OutputPane::WarningModel *model);
|
||||
void setUiFactory(ScxmlUiFactory *uifactory);
|
||||
|
||||
void setEditorInfo(const QString &key, const QString &value);
|
||||
void setDocument(ScxmlDocument *document);
|
||||
void unselectAll();
|
||||
void unhighlightAll();
|
||||
void highlightItems(const QVector<ScxmlTag*> &lstIds);
|
||||
void addConnectableItem(ItemType type, const QPointF &pos, BaseItem *parentItem);
|
||||
void runAutomaticLayout();
|
||||
void runLayoutToSelectedStates();
|
||||
void alignStates(int alignType);
|
||||
void adjustStates(int adjustType);
|
||||
void copy();
|
||||
void cut();
|
||||
void removeSelectedItems();
|
||||
void checkPaste();
|
||||
void paste(const QPointF &targetPos);
|
||||
void setTopMostScene(bool topmost);
|
||||
|
||||
ActionHandler *actionHandler() const;
|
||||
OutputPane::WarningModel *warningModel() const;
|
||||
ScxmlUiFactory *uiFactory() const;
|
||||
|
||||
signals:
|
||||
void openStateView(BaseItem *item);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
signals:
|
||||
void selectedStateCountChanged(int count);
|
||||
void selectedBaseItemCountChanged(int count);
|
||||
void pasteAvailable(bool para);
|
||||
|
||||
private slots:
|
||||
void warningVisibilityChanged(int type, WarningItem *item = nullptr);
|
||||
|
||||
private:
|
||||
void beginTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag, const QVariant &value);
|
||||
void endTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag, const QVariant &value);
|
||||
void selectionChanged(bool para);
|
||||
|
||||
friend class BaseItem;
|
||||
friend class WarningItem;
|
||||
|
||||
void init();
|
||||
qreal selectedMaxWidth() const;
|
||||
qreal selectedMaxHeight() const;
|
||||
void removeItems(const ScxmlTag *tag);
|
||||
void addChild(BaseItem *item);
|
||||
void removeChild(BaseItem *item);
|
||||
void addWarningItem(WarningItem *item);
|
||||
void removeWarningItem(WarningItem *item);
|
||||
void connectDocument();
|
||||
void disconnectDocument();
|
||||
|
||||
QPointer<ActionHandler> m_actionHandler;
|
||||
QPointer<OutputPane::WarningModel> m_warningModel;
|
||||
QPointer<ScxmlUiFactory> m_uiFactory;
|
||||
QPointer<ScxmlDocument> m_document;
|
||||
QVector<BaseItem*> m_baseItems;
|
||||
QVector<WarningItem*> m_allWarnings;
|
||||
int m_pasteCounter = 0;
|
||||
QPointer<BaseItem> m_lastPasteTargetItem;
|
||||
SnapLine *m_lineX = nullptr;
|
||||
SnapLine *m_lineY = nullptr;
|
||||
int m_selectedStateCount = 0;
|
||||
int m_selectedBaseItemCount = 0;
|
||||
int m_selectedStateTypeCount = 0;
|
||||
bool m_autoLayoutRunning = false;
|
||||
bool m_initializing = false;
|
||||
bool m_topMostScene = false;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
96
src/plugins/scxmleditor/plugin_interface/highlightitem.cpp
Normal file
96
src/plugins/scxmleditor/plugin_interface/highlightitem.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "highlightitem.h"
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
HighlightItem::HighlightItem(BaseItem *baseItem)
|
||||
: QGraphicsObject(nullptr)
|
||||
, m_baseItem(baseItem)
|
||||
{
|
||||
m_pen = QPen(QColor(0xff, 0x00, 0x60));
|
||||
m_pen.setWidth(2);
|
||||
m_pen.setStyle(Qt::DashLine);
|
||||
m_pen.setCosmetic(true);
|
||||
|
||||
setZValue(1000);
|
||||
}
|
||||
|
||||
void HighlightItem::advance(int phase)
|
||||
{
|
||||
Q_UNUSED(phase)
|
||||
|
||||
prepareGeometryChange();
|
||||
|
||||
if (m_baseItem) {
|
||||
setPos(m_baseItem->scenePos());
|
||||
m_boundingRect = m_baseItem->boundingRect();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
QRectF HighlightItem::boundingRect() const
|
||||
{
|
||||
return m_boundingRect;
|
||||
}
|
||||
|
||||
void HighlightItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(widget)
|
||||
|
||||
if (m_baseItem) {
|
||||
painter->save();
|
||||
painter->setRenderHints(QPainter::Antialiasing, true);
|
||||
|
||||
QRectF br = m_baseItem->polygonShape().boundingRect();
|
||||
|
||||
switch (m_baseItem->type()) {
|
||||
case StateType:
|
||||
case ParallelType: {
|
||||
painter->setOpacity(1.0);
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawRoundedRect(br, 10, 10);
|
||||
break;
|
||||
}
|
||||
case InitialStateType:
|
||||
case HistoryType:
|
||||
case FinalStateType: {
|
||||
painter->setOpacity(1.0);
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawEllipse(br);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
61
src/plugins/scxmleditor/plugin_interface/highlightitem.h
Normal file
61
src/plugins/scxmleditor/plugin_interface/highlightitem.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QGraphicsObject>
|
||||
#include <QPen>
|
||||
#include <QPointer>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class HighlightItem : public QGraphicsObject
|
||||
{
|
||||
public:
|
||||
HighlightItem(BaseItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return HighlightType;
|
||||
}
|
||||
|
||||
QRectF boundingRect() const override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
void advance(int phase) override;
|
||||
|
||||
private:
|
||||
QPointer<BaseItem> m_baseItem;
|
||||
QRectF m_boundingRect;
|
||||
QBrush m_brush;
|
||||
QPen m_pen;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
86
src/plugins/scxmleditor/plugin_interface/historyitem.cpp
Normal file
86
src/plugins/scxmleditor/plugin_interface/historyitem.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "historyitem.h"
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
HistoryItem::HistoryItem(const QPointF &pos, BaseItem *parent)
|
||||
: ConnectableItem(pos, parent)
|
||||
{
|
||||
setItemBoundingRect(QRectF(-20, -20, 40, 40));
|
||||
setMinimumHeight(40);
|
||||
setMinimumWidth(40);
|
||||
|
||||
m_pen.setColor(qRgb(0x12, 0x12, 0x12));
|
||||
m_pen.setWidth(2);
|
||||
}
|
||||
|
||||
void HistoryItem::updatePolygon()
|
||||
{
|
||||
QRectF r = boundingRect();
|
||||
m_size = qMin(r.width() * 0.45, r.height() * 0.45);
|
||||
QPointF center = r.center();
|
||||
|
||||
m_polygon.clear();
|
||||
m_polygon << (center + QPointF(-m_size, -m_size))
|
||||
<< (center + QPointF(m_size, -m_size))
|
||||
<< (center + QPointF(m_size, m_size))
|
||||
<< (center + QPointF(-m_size, m_size))
|
||||
<< (center + QPointF(-m_size, -m_size));
|
||||
}
|
||||
|
||||
void HistoryItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
ConnectableItem::paint(painter, option, widget);
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setOpacity(getOpacity());
|
||||
|
||||
painter->setBrush(QColor(0xff, 0xff, 0xff));
|
||||
m_pen.setColor(overlapping() ? qRgb(0xff, 0x00, 0x60) : qRgb(0x45, 0x45, 0x45));
|
||||
painter->setPen(m_pen);
|
||||
painter->drawEllipse(boundingRect().center(), m_size, m_size);
|
||||
|
||||
painter->drawText(boundingRect(), Qt::AlignCenter, QLatin1String(tagValue("type") == "deep" ? "H*" : "H"));
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
bool HistoryItem::canStartTransition(ItemType type) const
|
||||
{
|
||||
if (outputTransitionCount() > 0)
|
||||
return false;
|
||||
|
||||
switch (type) {
|
||||
case UnknownType:
|
||||
case StateType:
|
||||
case ParallelType:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
61
src/plugins/scxmleditor/plugin_interface/historyitem.h
Normal file
61
src/plugins/scxmleditor/plugin_interface/historyitem.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "connectableitem.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The HistoryItem class represents History-state of the SCXML-standard. It is an extended class from the ConnectableItem.
|
||||
*/
|
||||
class HistoryItem : public ConnectableItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HistoryItem(const QPointF &pos = QPointF(), BaseItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return HistoryType;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
protected:
|
||||
void updatePolygon() override;
|
||||
bool canStartTransition(ItemType type) const override;
|
||||
|
||||
private:
|
||||
qreal m_size;
|
||||
QPen m_pen;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
86
src/plugins/scxmleditor/plugin_interface/idwarningitem.cpp
Normal file
86
src/plugins/scxmleditor/plugin_interface/idwarningitem.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "idwarningitem.h"
|
||||
#include <QGraphicsScene>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
IdWarningItem::IdWarningItem(QGraphicsItem *parent)
|
||||
: WarningItem(parent)
|
||||
{
|
||||
setSeverity(OutputPane::Warning::ErrorType);
|
||||
setTypeName(tr("State"));
|
||||
setDescription(tr("Each State has to be unique ID."));
|
||||
setReason(tr("Missing ID"));
|
||||
setX(-boundingRect().width());
|
||||
}
|
||||
|
||||
void IdWarningItem::check()
|
||||
{
|
||||
setId(m_id);
|
||||
}
|
||||
|
||||
void IdWarningItem::setId(const QString &text)
|
||||
{
|
||||
QString oldId = m_id;
|
||||
m_id = text;
|
||||
|
||||
// Check old id
|
||||
if (!oldId.isEmpty())
|
||||
checkDuplicates(oldId);
|
||||
|
||||
// Check new id
|
||||
if (m_id.isEmpty()) {
|
||||
setReason(tr("Missing ID"));
|
||||
setWarningActive(true);
|
||||
} else
|
||||
checkDuplicates(m_id);
|
||||
}
|
||||
|
||||
void IdWarningItem::checkDuplicates(const QString &id)
|
||||
{
|
||||
if (scene()) {
|
||||
QVector<IdWarningItem*> foundItems;
|
||||
|
||||
QList<QGraphicsItem*> items = scene()->items();
|
||||
for (int i = 0; i < items.count(); ++i) {
|
||||
if (items[i]->type() == IdWarningType) {
|
||||
auto item = qgraphicsitem_cast<IdWarningItem*>(items[i]);
|
||||
if (item && item->id() == id)
|
||||
foundItems << item;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundItems.count() == 1) {
|
||||
foundItems[0]->setWarningActive(false);
|
||||
} else {
|
||||
for (int i = 0; i < foundItems.count(); ++i) {
|
||||
foundItems[i]->setReason(tr("Duplicate ID (%1)").arg(id));
|
||||
foundItems[i]->setWarningActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
61
src/plugins/scxmleditor/plugin_interface/idwarningitem.h
Normal file
61
src/plugins/scxmleditor/plugin_interface/idwarningitem.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "warningitem.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class IdWarningItem : public WarningItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IdWarningItem(QGraphicsItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return IdWarningType;
|
||||
}
|
||||
|
||||
QString id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
void check() override;
|
||||
void setId(const QString &text);
|
||||
|
||||
private:
|
||||
void checkDuplicates(const QString &id);
|
||||
|
||||
QString m_id;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
33
src/plugins/scxmleditor/plugin_interface/imageprovider.cpp
Normal file
33
src/plugins/scxmleditor/plugin_interface/imageprovider.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "imageprovider.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ImageProvider::ImageProvider(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
47
src/plugins/scxmleditor/plugin_interface/imageprovider.h
Normal file
47
src/plugins/scxmleditor/plugin_interface/imageprovider.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlTag;
|
||||
|
||||
class ImageProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ImageProvider(QObject *parent = nullptr);
|
||||
|
||||
virtual QImage *backgroundImage(const ScxmlTag *tag) const = 0;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
134
src/plugins/scxmleditor/plugin_interface/initialstateitem.cpp
Normal file
134
src/plugins/scxmleditor/plugin_interface/initialstateitem.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "initialstateitem.h"
|
||||
#include "initialwarningitem.h"
|
||||
#include "graphicsitemprovider.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "scxmluifactory.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDataStream>
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
InitialStateItem::InitialStateItem(const QPointF &pos, BaseItem *parent)
|
||||
: ConnectableItem(pos, parent)
|
||||
{
|
||||
setItemBoundingRect(QRectF(-20, -20, 40, 40));
|
||||
setMinimumHeight(40);
|
||||
setMinimumWidth(40);
|
||||
m_pen.setColor(qRgb(0x12, 0x12, 0x12));
|
||||
m_pen.setWidth(2);
|
||||
|
||||
checkWarningItems();
|
||||
}
|
||||
|
||||
void InitialStateItem::checkWarningItems()
|
||||
{
|
||||
ScxmlUiFactory *uifactory = uiFactory();
|
||||
if (uifactory) {
|
||||
auto provider = static_cast<GraphicsItemProvider*>(uifactory->object("graphicsItemProvider"));
|
||||
if (provider) {
|
||||
if (!m_warningItem)
|
||||
m_warningItem = static_cast<InitialWarningItem*>(provider->createWarningItem(Constants::C_STATE_WARNING_INITIAL, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariant InitialStateItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
QVariant retValue = ConnectableItem::itemChange(change, value);
|
||||
|
||||
switch (change) {
|
||||
case QGraphicsItem::ItemSceneHasChanged:
|
||||
checkWarningItems();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
void InitialStateItem::updatePolygon()
|
||||
{
|
||||
QRectF r = boundingRect();
|
||||
m_size = qMin(r.width() * 0.45, r.height() * 0.45);
|
||||
QPointF center = r.center();
|
||||
|
||||
m_polygon.clear();
|
||||
m_polygon << (center + QPointF(-m_size, -m_size))
|
||||
<< (center + QPointF(m_size, -m_size))
|
||||
<< (center + QPointF(m_size, m_size))
|
||||
<< (center + QPointF(-m_size, m_size))
|
||||
<< (center + QPointF(-m_size, -m_size));
|
||||
|
||||
if (m_warningItem)
|
||||
m_warningItem->updatePos();
|
||||
}
|
||||
|
||||
void InitialStateItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
ConnectableItem::paint(painter, option, widget);
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setOpacity(getOpacity());
|
||||
|
||||
m_pen.setColor(overlapping() ? qRgb(0xff, 0x00, 0x60) : qRgb(0x45, 0x45, 0x45));
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(QColor(0x4d, 0x4d, 0x4d));
|
||||
painter->drawEllipse(boundingRect().center(), m_size, m_size);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
InitialWarningItem *InitialStateItem::warningItem() const
|
||||
{
|
||||
return m_warningItem;
|
||||
}
|
||||
|
||||
bool InitialStateItem::canStartTransition(ItemType type) const
|
||||
{
|
||||
if (transitionCount() > 0)
|
||||
return false;
|
||||
|
||||
switch (type) {
|
||||
case UnknownType:
|
||||
case StateType:
|
||||
case ParallelType:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void InitialStateItem::checkWarnings()
|
||||
{
|
||||
if (m_warningItem)
|
||||
m_warningItem->check();
|
||||
}
|
||||
67
src/plugins/scxmleditor/plugin_interface/initialstateitem.h
Normal file
67
src/plugins/scxmleditor/plugin_interface/initialstateitem.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "connectableitem.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class InitialWarningItem;
|
||||
|
||||
/**
|
||||
* @brief The InitialStateItem class represents Initial-state of the SCXML-standard. It is a extended class from the ConnectableItem.
|
||||
*/
|
||||
class InitialStateItem : public ConnectableItem
|
||||
{
|
||||
public:
|
||||
explicit InitialStateItem(const QPointF &pos = QPointF(), BaseItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return InitialStateType;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
InitialWarningItem *warningItem() const;
|
||||
|
||||
void checkWarnings() override;
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
void updatePolygon() override;
|
||||
bool canStartTransition(ItemType type) const override;
|
||||
|
||||
private:
|
||||
void checkWarningItems();
|
||||
InitialWarningItem *m_warningItem = nullptr;
|
||||
qreal m_size = 1.0;
|
||||
QPen m_pen;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "initialwarningitem.h"
|
||||
#include "initialstateitem.h"
|
||||
#include "sceneutils.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
InitialWarningItem::InitialWarningItem(InitialStateItem *parent)
|
||||
: WarningItem(parent)
|
||||
, m_parentItem(parent)
|
||||
{
|
||||
setSeverity(OutputPane::Warning::ErrorType);
|
||||
setTypeName(tr("Initial"));
|
||||
setDescription(tr("It is possible to have max 1 initial-state in the same level."));
|
||||
setReason(tr("Too many initial states in the same level"));
|
||||
}
|
||||
|
||||
void InitialWarningItem::updatePos()
|
||||
{
|
||||
setPos(m_parentItem->boundingRect().topLeft());
|
||||
}
|
||||
|
||||
void InitialWarningItem::check()
|
||||
{
|
||||
if (m_parentItem)
|
||||
setWarningActive(SceneUtils::hasSiblingStates(m_parentItem));
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "warningitem.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class InitialStateItem;
|
||||
|
||||
class InitialWarningItem : public WarningItem
|
||||
{
|
||||
public:
|
||||
InitialWarningItem(InitialStateItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return InitialWarningType;
|
||||
}
|
||||
|
||||
void check() override;
|
||||
|
||||
void updatePos();
|
||||
|
||||
private:
|
||||
InitialStateItem *m_parentItem;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
78
src/plugins/scxmleditor/plugin_interface/isceditor.h
Normal file
78
src/plugins/scxmleditor/plugin_interface/isceditor.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mytypes.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlUiFactory;
|
||||
class ScxmlDocument;
|
||||
|
||||
/**
|
||||
* @brief The ISCEditor interface for the all SCEditor plugins
|
||||
*
|
||||
* Every SCEditor plugin must implement this interface. SCEditor application will load all plugins which have listed
|
||||
* in the environment variable QT_SCEDITOR_PLUGINS and which implements this interface. The function init() will be called
|
||||
* immediately after plugin has successfully loaded. See the @ScxmlUiFactory for more information how to register editor etc for the UI.
|
||||
* The function refresh() will be called when it is time to refresh data. Plugin itself can decide if this is necessary or not.
|
||||
* Normally this function will be called when application get focus.
|
||||
*/
|
||||
class ISCEditor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief init - pure virtual function to init and forward the pointer of the ScxmlUiFactory to the plugin.
|
||||
* @param factory - pointer to the ScxmlUiFactory
|
||||
*/
|
||||
virtual void init(ScxmlUiFactory *factory) = 0;
|
||||
|
||||
/**
|
||||
* @brief documentChanged - when document will changed this function will be called
|
||||
* @param type - change reason
|
||||
* @param doc - pointer to ScxmlDocument
|
||||
*/
|
||||
virtual void documentChanged(DocumentChangeType type, ScxmlDocument *doc) = 0;
|
||||
|
||||
/**
|
||||
* @brief refresh - tell the plugin that it is time to update all data if necessary
|
||||
*/
|
||||
virtual void refresh() = 0;
|
||||
|
||||
/**
|
||||
* @brief detach - here should be unregister all objects
|
||||
*/
|
||||
virtual void detach() = 0;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
Q_DECLARE_INTERFACE(ScxmlEditor::PluginInterface::ISCEditor, "StateChartEditor.ISCEditor/1.0")
|
||||
QT_END_NAMESPACE
|
||||
53
src/plugins/scxmleditor/plugin_interface/layoutitem.cpp
Normal file
53
src/plugins/scxmleditor/plugin_interface/layoutitem.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "layoutitem.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
LayoutItem::LayoutItem(const QRectF &br, QGraphicsItem *parent)
|
||||
: QGraphicsObject(parent)
|
||||
, m_boundingRect(br)
|
||||
{
|
||||
setZValue(-100);
|
||||
}
|
||||
|
||||
QRectF LayoutItem::boundingRect() const
|
||||
{
|
||||
return m_boundingRect;
|
||||
}
|
||||
|
||||
void LayoutItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(painter)
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(widget)
|
||||
}
|
||||
|
||||
void LayoutItem::setBoundingRect(const QRectF &r)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
m_boundingRect = r;
|
||||
}
|
||||
55
src/plugins/scxmleditor/plugin_interface/layoutitem.h
Normal file
55
src/plugins/scxmleditor/plugin_interface/layoutitem.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mytypes.h"
|
||||
#include <QGraphicsObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class LayoutItem : public QGraphicsObject
|
||||
{
|
||||
public:
|
||||
LayoutItem(const QRectF &br, QGraphicsItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return LayoutType;
|
||||
}
|
||||
|
||||
QRectF boundingRect() const override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
void setBoundingRect(const QRectF &r);
|
||||
|
||||
private:
|
||||
QRectF m_boundingRect;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
115
src/plugins/scxmleditor/plugin_interface/mytypes.h
Normal file
115
src/plugins/scxmleditor/plugin_interface/mytypes.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The type of the graphics-items
|
||||
*/
|
||||
enum ItemType {
|
||||
UnknownType = QGraphicsItem::UserType + 1,
|
||||
|
||||
// Warning items ->
|
||||
HighlightType,
|
||||
LayoutType,
|
||||
IdWarningType,
|
||||
StateWarningType,
|
||||
TransitionWarningType,
|
||||
InitialWarningType,
|
||||
|
||||
// Helper items ->
|
||||
CornerGrabberType,
|
||||
QuickTransitionType,
|
||||
TextType,
|
||||
TagTextType,
|
||||
TagWrapperType,
|
||||
TransitionType,
|
||||
|
||||
// Connectable-items ->
|
||||
InitialStateType,
|
||||
FinalStateType,
|
||||
HistoryType,
|
||||
StateType,
|
||||
ParallelType
|
||||
};
|
||||
|
||||
enum ActionType {
|
||||
ActionZoomIn = 0,
|
||||
ActionZoomOut,
|
||||
ActionFitToView,
|
||||
ActionPan,
|
||||
ActionMagnifier,
|
||||
ActionNavigator,
|
||||
ActionCopy,
|
||||
ActionCut,
|
||||
ActionPaste,
|
||||
ActionScreenshot,
|
||||
ActionExportToImage,
|
||||
ActionFullNamespace,
|
||||
ActionAlignLeft,
|
||||
ActionAlignRight,
|
||||
ActionAlignTop,
|
||||
ActionAlignBottom,
|
||||
ActionAlignHorizontal,
|
||||
ActionAlignVertical,
|
||||
ActionAdjustWidth,
|
||||
ActionAdjustHeight,
|
||||
ActionAdjustSize,
|
||||
ActionStatistics,
|
||||
ActionLast,
|
||||
|
||||
ActionColorTheme
|
||||
};
|
||||
|
||||
enum ToolButtonType {
|
||||
ToolButtonStateColor,
|
||||
ToolButtonFontColor,
|
||||
ToolButtonAlignment,
|
||||
ToolButtonAdjustment,
|
||||
ToolButtonLast,
|
||||
|
||||
ToolButtonColorTheme
|
||||
};
|
||||
|
||||
enum AttributeRole {
|
||||
DataTypeRole = Qt::UserRole + 1,
|
||||
DataRole
|
||||
};
|
||||
|
||||
enum DocumentChangeType {
|
||||
BeginSave = 0,
|
||||
AfterSave,
|
||||
AfterLoad,
|
||||
NewDocument
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
117
src/plugins/scxmleditor/plugin_interface/parallelitem.cpp
Normal file
117
src/plugins/scxmleditor/plugin_interface/parallelitem.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "parallelitem.h"
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmltagutils.h"
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ParallelItem::ParallelItem(const QPointF &pos, BaseItem *parent)
|
||||
: StateItem(pos, parent)
|
||||
{
|
||||
m_pixmap = QPixmap(":/scxmleditor/images/parallel_icon.png");
|
||||
updatePolygon();
|
||||
}
|
||||
|
||||
void ParallelItem::updatePolygon()
|
||||
{
|
||||
StateItem::updatePolygon();
|
||||
int cap = m_titleRect.height() * 0.2;
|
||||
m_pixmapRect = m_titleRect.adjusted(m_titleRect.width() - m_titleRect.height(), cap, -cap, -cap).toRect();
|
||||
}
|
||||
|
||||
void ParallelItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
StateItem::paint(painter, option, widget);
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setOpacity(getOpacity());
|
||||
|
||||
painter->drawPixmap(m_pixmapRect, m_pixmap);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void ParallelItem::doLayout(int d)
|
||||
{
|
||||
if (depth() != d)
|
||||
return;
|
||||
|
||||
// 1. Find children items
|
||||
QVector<StateItem*> children;
|
||||
foreach (QGraphicsItem *it, childItems()) {
|
||||
if (it->type() >= StateType) {
|
||||
auto itt = qgraphicsitem_cast<StateItem*>(it);
|
||||
if (itt)
|
||||
children << itt;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Adjust sizes
|
||||
foreach (StateItem *itt, children) {
|
||||
itt->shrink();
|
||||
}
|
||||
|
||||
qreal maxw = 0;
|
||||
foreach (StateItem *itt, children) {
|
||||
QRectF rr = itt->boundingRect();
|
||||
maxw = qMax(rr.width(), maxw);
|
||||
}
|
||||
|
||||
foreach (StateItem *itt, children) {
|
||||
QRectF rr = itt->boundingRect();
|
||||
if (!qFuzzyCompare(rr.width(), maxw))
|
||||
rr.setWidth(maxw);
|
||||
itt->setItemBoundingRect(rr);
|
||||
}
|
||||
|
||||
// 3. Relocate children-states
|
||||
// a) sort list
|
||||
QVector<StateItem*> sortedList;
|
||||
while (children.count() > 0) {
|
||||
qreal minTop = children.first()->boundingRect().top();
|
||||
int minTopIndex = 0;
|
||||
for (int i = 1; i < children.count(); ++i) {
|
||||
qreal top = children[i]->boundingRect().top();
|
||||
if (top < minTop) {
|
||||
minTop = top;
|
||||
minTopIndex = i;
|
||||
}
|
||||
}
|
||||
sortedList << children.takeAt(minTopIndex);
|
||||
}
|
||||
|
||||
// b) relocate items
|
||||
for (int i = 1; i < sortedList.count(); ++i) {
|
||||
QRectF br1 = sortedList[i - 1]->sceneBoundingRect();
|
||||
QRectF br2 = sortedList[i]->sceneBoundingRect();
|
||||
sortedList[i]->moveStateBy(br1.left() - br2.left(), br1.bottom() + 10 - br2.top());
|
||||
}
|
||||
|
||||
// 4. Shrink parallel-state
|
||||
shrink();
|
||||
}
|
||||
59
src/plugins/scxmleditor/plugin_interface/parallelitem.h
Normal file
59
src/plugins/scxmleditor/plugin_interface/parallelitem.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stateitem.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The ParalllelItem class represents Parallel-state of the SCXML-standard. It is a extended class from the StateItem.
|
||||
*/
|
||||
class ParallelItem : public StateItem
|
||||
{
|
||||
public:
|
||||
explicit ParallelItem(const QPointF &pos = QPointF(), BaseItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return ParallelType;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
void doLayout(int d) override;
|
||||
|
||||
protected:
|
||||
void updatePolygon() override;
|
||||
|
||||
private:
|
||||
QPixmap m_pixmap;
|
||||
QRect m_pixmapRect;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,93 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/actionhandler.h \
|
||||
$$PWD/actionprovider.h \
|
||||
$$PWD/attributeitemdelegate.h \
|
||||
$$PWD/attributeitemmodel.h \
|
||||
$$PWD/baseitem.h \
|
||||
$$PWD/connectableitem.h \
|
||||
$$PWD/cornergrabberitem.h \
|
||||
$$PWD/finalstateitem.h \
|
||||
$$PWD/genericscxmlplugin.h \
|
||||
$$PWD/graphicsitemprovider.h \
|
||||
$$PWD/graphicsscene.h \
|
||||
$$PWD/highlightitem.h \
|
||||
$$PWD/historyitem.h \
|
||||
$$PWD/idwarningitem.h \
|
||||
$$PWD/imageprovider.h \
|
||||
$$PWD/initialstateitem.h \
|
||||
$$PWD/initialwarningitem.h \
|
||||
$$PWD/isceditor.h \
|
||||
$$PWD/layoutitem.h \
|
||||
$$PWD/mytypes.h \
|
||||
$$PWD/parallelitem.h \
|
||||
$$PWD/quicktransitionitem.h \
|
||||
$$PWD/scattributeitemdelegate.h \
|
||||
$$PWD/scattributeitemmodel.h \
|
||||
$$PWD/sceneutils.h \
|
||||
$$PWD/scgraphicsitemprovider.h \
|
||||
$$PWD/scshapeprovider.h \
|
||||
$$PWD/scutilsprovider.h \
|
||||
$$PWD/scxmldocument.h \
|
||||
$$PWD/scxmlnamespace.h \
|
||||
$$PWD/scxmltag.h \
|
||||
$$PWD/scxmltagutils.h \
|
||||
$$PWD/scxmltypes.h \
|
||||
$$PWD/scxmluifactory.h \
|
||||
$$PWD/serializer.h \
|
||||
$$PWD/shapeprovider.h \
|
||||
$$PWD/snapline.h \
|
||||
$$PWD/stateitem.h \
|
||||
$$PWD/statewarningitem.h \
|
||||
$$PWD/tagtextitem.h \
|
||||
$$PWD/textitem.h \
|
||||
$$PWD/transitionitem.h \
|
||||
$$PWD/transitionwarningitem.h \
|
||||
$$PWD/undocommands.h \
|
||||
$$PWD/utilsprovider.h \
|
||||
$$PWD/warningitem.h \
|
||||
$$PWD/warningprovider.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/actionhandler.cpp \
|
||||
$$PWD/attributeitemdelegate.cpp \
|
||||
$$PWD/attributeitemmodel.cpp \
|
||||
$$PWD/baseitem.cpp \
|
||||
$$PWD/connectableitem.cpp \
|
||||
$$PWD/cornergrabberitem.cpp \
|
||||
$$PWD/finalstateitem.cpp \
|
||||
$$PWD/genericscxmlplugin.cpp \
|
||||
$$PWD/graphicsscene.cpp \
|
||||
$$PWD/highlightitem.cpp \
|
||||
$$PWD/historyitem.cpp \
|
||||
$$PWD/idwarningitem.cpp \
|
||||
$$PWD/imageprovider.cpp \
|
||||
$$PWD/initialstateitem.cpp \
|
||||
$$PWD/initialwarningitem.cpp \
|
||||
$$PWD/layoutitem.cpp \
|
||||
$$PWD/parallelitem.cpp \
|
||||
$$PWD/quicktransitionitem.cpp \
|
||||
$$PWD/scattributeitemdelegate.cpp \
|
||||
$$PWD/scattributeitemmodel.cpp \
|
||||
$$PWD/sceneutils.cpp \
|
||||
$$PWD/scgraphicsitemprovider.cpp \
|
||||
$$PWD/scshapeprovider.cpp \
|
||||
$$PWD/scutilsprovider.cpp \
|
||||
$$PWD/scxmldocument.cpp \
|
||||
$$PWD/scxmlnamespace.cpp \
|
||||
$$PWD/scxmltag.cpp \
|
||||
$$PWD/scxmltagutils.cpp \
|
||||
$$PWD/scxmluifactory.cpp \
|
||||
$$PWD/serializer.cpp \
|
||||
$$PWD/shapeprovider.cpp \
|
||||
$$PWD/snapline.cpp \
|
||||
$$PWD/stateitem.cpp \
|
||||
$$PWD/statewarningitem.cpp \
|
||||
$$PWD/tagtextitem.cpp \
|
||||
$$PWD/textitem.cpp \
|
||||
$$PWD/transitionitem.cpp \
|
||||
$$PWD/transitionwarningitem.cpp \
|
||||
$$PWD/undocommands.cpp \
|
||||
$$PWD/utilsprovider.cpp \
|
||||
$$PWD/warningitem.cpp
|
||||
133
src/plugins/scxmleditor/plugin_interface/quicktransitionitem.cpp
Normal file
133
src/plugins/scxmleditor/plugin_interface/quicktransitionitem.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "quicktransitionitem.h"
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
const qreal CAPX = 4;
|
||||
const qreal CAPY = 3;
|
||||
|
||||
QuickTransitionItem::QuickTransitionItem(int index, ItemType connectionType, QGraphicsItem *parent)
|
||||
: QGraphicsObject(parent)
|
||||
, m_connectionType(connectionType)
|
||||
{
|
||||
setParentItem(parent);
|
||||
installSceneEventFilter(parent);
|
||||
setZValue(501);
|
||||
|
||||
m_rect = QRectF(index * 25, -30, 20, 20);
|
||||
m_drawingRect = m_rect.adjusted(4, 4, -4, -4);
|
||||
m_stateRect = m_rect.adjusted(3, 4, -3, -4);
|
||||
m_brush.setStyle(Qt::SolidPattern);
|
||||
m_brush.setColor(QColor(0xe8, 0xe8, 0xe8));
|
||||
|
||||
m_pen.setColor(QColor(0x12, 0x12, 0x12));
|
||||
m_pen.setCapStyle(Qt::RoundCap);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
void QuickTransitionItem::setConnectionType(ItemType connectionType)
|
||||
{
|
||||
m_connectionType = connectionType;
|
||||
}
|
||||
|
||||
void QuickTransitionItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
Q_UNUSED(e)
|
||||
m_brush.setColor(QColor(0xe8, 0xe8, 0xe8));
|
||||
update();
|
||||
}
|
||||
|
||||
void QuickTransitionItem::hoverEnterEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
Q_UNUSED(e)
|
||||
m_brush.setColor(QColor(0xff, 0xc4, 0xff));
|
||||
update();
|
||||
}
|
||||
|
||||
void QuickTransitionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(widget)
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(m_brush);
|
||||
painter->drawRect(m_rect);
|
||||
|
||||
if (m_connectionType == UnknownType) {
|
||||
QPointF endPoint = m_drawingRect.topRight();
|
||||
painter->drawLine(m_drawingRect.bottomLeft(), endPoint);
|
||||
painter->drawLine(endPoint, endPoint + QPointF(-5, 0));
|
||||
painter->drawLine(endPoint, endPoint + QPointF(0, 5));
|
||||
} else if (m_connectionType >= FinalStateType) {
|
||||
switch (m_connectionType) {
|
||||
case StateType:
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawRoundedRect(m_stateRect, 2, 2);
|
||||
break;
|
||||
|
||||
case ParallelType:
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawRoundedRect(m_stateRect, 2, 2);
|
||||
|
||||
painter->setPen(m_pen);
|
||||
painter->drawLine(QPointF(m_stateRect.left() + CAPX, m_stateRect.center().y()), QPointF(m_stateRect.right() - CAPX, m_stateRect.center().y()));
|
||||
painter->drawLine(QPointF(m_stateRect.center().x(), m_stateRect.top() + CAPY), QPointF(m_stateRect.center().x(), m_stateRect.bottom() - CAPY));
|
||||
painter->drawLine(QPointF(m_stateRect.right() - CAPX, m_stateRect.top() + CAPY), QPointF(m_stateRect.center().x(), m_stateRect.top() + CAPY));
|
||||
painter->drawLine(QPointF(m_stateRect.right() - CAPX, m_stateRect.bottom() - CAPY), QPointF(m_stateRect.center().x(), m_stateRect.bottom() - CAPY));
|
||||
break;
|
||||
|
||||
case FinalStateType:
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawEllipse(m_stateRect.center(), 7, 7);
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(Qt::black);
|
||||
painter->drawEllipse(m_stateRect.center(), 5, 5);
|
||||
break;
|
||||
|
||||
case HistoryType:
|
||||
painter->setFont(QFont("Arial", 6));
|
||||
painter->setPen(m_pen);
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawEllipse(m_stateRect.center(), 7, 7);
|
||||
painter->drawText(m_stateRect, Qt::AlignCenter, tr("H"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class QuickTransitionItem : public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QuickTransitionItem(int index = 0, ItemType connectionType = UnknownType, QGraphicsItem *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief type of the item
|
||||
*/
|
||||
int type() const override
|
||||
{
|
||||
return QuickTransitionType;
|
||||
}
|
||||
|
||||
ItemType connectionType() const
|
||||
{
|
||||
return m_connectionType;
|
||||
}
|
||||
|
||||
void setConnectionType(ItemType type);
|
||||
|
||||
QRectF boundingRect() const override
|
||||
{
|
||||
return m_rect;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
private:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
|
||||
ItemType m_connectionType;
|
||||
QRectF m_rect;
|
||||
QBrush m_brush;
|
||||
QRectF m_drawingRect;
|
||||
QRectF m_stateRect;
|
||||
QPen m_pen;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scattributeitemdelegate.h"
|
||||
#include "mytypes.h"
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QRegExp>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
SCAttributeItemDelegate::SCAttributeItemDelegate(QObject *parent)
|
||||
: AttributeItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget *SCAttributeItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
|
||||
switch (index.data(DataTypeRole).toInt()) {
|
||||
case QVariant::StringList: {
|
||||
auto combo = new QComboBox(parent);
|
||||
combo->setFocusPolicy(Qt::StrongFocus);
|
||||
return combo;
|
||||
}
|
||||
case QVariant::String: {
|
||||
if (index.column() == 0) {
|
||||
auto edit = new QLineEdit(parent);
|
||||
edit->setFocusPolicy(Qt::StrongFocus);
|
||||
QRegExp rx("^(?!xml)[_a-z][a-z0-9-._]*$");
|
||||
rx.setCaseSensitivity(Qt::CaseInsensitive);
|
||||
edit->setValidator(new QRegExpValidator(rx, parent));
|
||||
return edit;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
}
|
||||
|
||||
void SCAttributeItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QStyledItemDelegate::updateEditorGeometry(editor, option, index);
|
||||
if (editor)
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
void SCAttributeItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
switch (index.data(DataTypeRole).toInt()) {
|
||||
case QVariant::StringList: {
|
||||
auto combo = qobject_cast<QComboBox*>(editor);
|
||||
if (combo) {
|
||||
combo->clear();
|
||||
QStringList values = index.data(DataRole).toString().split(";");
|
||||
|
||||
foreach (QString val, values)
|
||||
combo->addItem(val);
|
||||
|
||||
combo->setCurrentText(index.data().toString());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
}
|
||||
|
||||
void SCAttributeItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
auto combo = qobject_cast<QComboBox*>(editor);
|
||||
if (combo) {
|
||||
model->setData(index, combo->currentText());
|
||||
return;
|
||||
}
|
||||
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "attributeitemdelegate.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class SCAttributeItemDelegate : public AttributeItemDelegate
|
||||
{
|
||||
public:
|
||||
SCAttributeItemDelegate(QObject *parent = nullptr);
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,171 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scattributeitemmodel.h"
|
||||
#include "mytypes.h"
|
||||
|
||||
#include <QBrush>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
SCAttributeItemModel::SCAttributeItemModel(QObject *parent)
|
||||
: AttributeItemModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant SCAttributeItemModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return section == 0 ? tr("Name") : tr("Value");
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool SCAttributeItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole || m_tag == nullptr)
|
||||
return false;
|
||||
|
||||
bool bEditable = m_tag->tagType() <= MetadataItem;
|
||||
|
||||
if (index.row() >= 0 && m_document != 0) {
|
||||
if (!bEditable) {
|
||||
if (index.row() < m_tag->info()->n_attributes)
|
||||
m_document->setValue(m_tag, index.row(), value.toString());
|
||||
} else {
|
||||
if (index.column() == 0) {
|
||||
m_tag->setAttributeName(index.row(), value.toString());
|
||||
m_document->setValue(m_tag, value.toString(), m_tag->attribute(value.toString()));
|
||||
} else
|
||||
m_document->setValue(m_tag, m_tag->attributeName(index.row()), value.toString());
|
||||
}
|
||||
emit dataChanged(index, index);
|
||||
emit layoutChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant SCAttributeItemModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || m_tag == nullptr)
|
||||
return QVariant();
|
||||
|
||||
if (index.row() < 0)
|
||||
return QVariant();
|
||||
|
||||
bool bEditable = m_tag->tagType() <= MetadataItem;
|
||||
|
||||
if (!bEditable && index.row() >= m_tag->info()->n_attributes)
|
||||
return QVariant();
|
||||
|
||||
if (bEditable && index.row() > m_tag->attributeCount())
|
||||
return QVariant();
|
||||
|
||||
bool bExtraRow = bEditable && m_tag->attributeCount() == index.row();
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
if (bExtraRow)
|
||||
return index.column() == 0 ? tr("- name -") : tr(" - value -");
|
||||
case Qt::EditRole: {
|
||||
if (index.column() == 0) {
|
||||
if (bEditable) {
|
||||
return m_tag->attributeName(index.row());
|
||||
} else {
|
||||
if (m_tag->info()->attributes[index.row()].required)
|
||||
return QString::fromLatin1("*%1").arg(QLatin1String(m_tag->info()->attributes[index.row()].name));
|
||||
else
|
||||
return m_tag->info()->attributes[index.row()].name;
|
||||
}
|
||||
} else {
|
||||
if (bEditable) {
|
||||
if (m_tag->tagType() > MetadataItem && m_tag->info()->attributes[index.row()].datatype == QVariant::StringList)
|
||||
return QString::fromLatin1(m_tag->info()->attributes[index.row()].value).split(";");
|
||||
else
|
||||
return m_tag->attribute(index.row());
|
||||
} else {
|
||||
return m_tag->attribute(QLatin1String(m_tag->info()->attributes[index.row()].name));
|
||||
}
|
||||
}
|
||||
}
|
||||
case Qt::TextAlignmentRole:
|
||||
if (bExtraRow)
|
||||
return Qt::AlignHCenter;
|
||||
else
|
||||
break;
|
||||
case Qt::ForegroundRole:
|
||||
return bExtraRow ? QBrush(Qt::gray) : QBrush(Qt::black);
|
||||
case DataTypeRole: {
|
||||
if (m_tag->tagType() == Metadata || m_tag->tagType() == MetadataItem)
|
||||
return (int)QVariant::String;
|
||||
else if (index.column() == 1 && m_tag->info()->n_attributes > 0)
|
||||
return m_tag->info()->attributes[index.row()].datatype;
|
||||
else
|
||||
return QVariant::Invalid;
|
||||
}
|
||||
case DataRole: {
|
||||
if (m_tag->info()->n_attributes > 0)
|
||||
return m_tag->info()->attributes[index.row()].value;
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags SCAttributeItemModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid() || m_tag == nullptr)
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
if (m_tag->tagType() <= MetadataItem || (index.column() == 1 && m_tag->info()->n_attributes > 0 && m_tag->info()->attributes[index.row()].editable))
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
|
||||
|
||||
return Qt::NoItemFlags;
|
||||
}
|
||||
|
||||
int SCAttributeItemModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return 2;
|
||||
}
|
||||
|
||||
int SCAttributeItemModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
if (m_tag) {
|
||||
if (m_tag->tagType() <= MetadataItem)
|
||||
return m_tag->attributeCount() + 1;
|
||||
else
|
||||
return m_tag->info()->n_attributes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "attributeitemmodel.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class SCAttributeItemModel : public AttributeItemModel
|
||||
{
|
||||
public:
|
||||
SCAttributeItemModel(QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
419
src/plugins/scxmleditor/plugin_interface/sceneutils.cpp
Normal file
419
src/plugins/scxmleditor/plugin_interface/sceneutils.cpp
Normal file
@@ -0,0 +1,419 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "sceneutils.h"
|
||||
#include "connectableitem.h"
|
||||
#include "finalstateitem.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "historyitem.h"
|
||||
#include "initialstateitem.h"
|
||||
#include "parallelitem.h"
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "scxmltag.h"
|
||||
#include "scxmltagutils.h"
|
||||
#include "stateitem.h"
|
||||
#include "transitionitem.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QGraphicsScene>
|
||||
#include <QtMath>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
namespace SceneUtils {
|
||||
|
||||
ConnectableItem *createItem(ItemType type, const QPointF &pos)
|
||||
{
|
||||
switch (type) {
|
||||
case InitialStateType:
|
||||
return new InitialStateItem(pos);
|
||||
case FinalStateType:
|
||||
return new FinalStateItem(pos);
|
||||
case StateType:
|
||||
return new StateItem(pos);
|
||||
case HistoryType:
|
||||
return new HistoryItem(pos);
|
||||
case ParallelType:
|
||||
return new ParallelItem(pos);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ConnectableItem *createItemByTagType(TagType type, const QPointF &pos)
|
||||
{
|
||||
switch (type) {
|
||||
case Initial:
|
||||
return createItem(InitialStateType, pos);
|
||||
case Final:
|
||||
return createItem(FinalStateType, pos);
|
||||
case State:
|
||||
return createItem(StateType, pos);
|
||||
case History:
|
||||
return createItem(HistoryType, pos);
|
||||
case Parallel:
|
||||
return createItem(ParallelType, pos);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ScxmlTag *createTag(ItemType type, ScxmlDocument *document)
|
||||
{
|
||||
TagType t = UnknownTag;
|
||||
switch (type) {
|
||||
case InitialStateType:
|
||||
t = Initial;
|
||||
break;
|
||||
case FinalStateType:
|
||||
t = Final;
|
||||
break;
|
||||
case HistoryType:
|
||||
t = History;
|
||||
break;
|
||||
case StateType:
|
||||
t = State;
|
||||
break;
|
||||
case ParallelType:
|
||||
t = Parallel;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (t != UnknownTag)
|
||||
return new ScxmlTag(t, document);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool canDrop(int parentType, int childType)
|
||||
{
|
||||
switch (parentType) {
|
||||
case StateType: {
|
||||
switch (childType) {
|
||||
case InitialStateType:
|
||||
case FinalStateType:
|
||||
case StateType:
|
||||
case ParallelType:
|
||||
case HistoryType:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case ParallelType: {
|
||||
switch (childType) {
|
||||
case StateType:
|
||||
case ParallelType:
|
||||
case HistoryType:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<ScxmlTag*> findCopyTags(const QVector<BaseItem*> &items, QPointF &minPos)
|
||||
{
|
||||
QPointF pp(0, 0);
|
||||
QVector<ScxmlTag*> tags;
|
||||
foreach (BaseItem *it, items) {
|
||||
if (it->type() >= InitialStateType && it->isSelected()) {
|
||||
BaseItem *parent = it->parentBaseItem();
|
||||
BaseItem *lastSelectedParent = it;
|
||||
while (parent) {
|
||||
if (parent->isSelected())
|
||||
lastSelectedParent = parent;
|
||||
parent = parent->parentBaseItem();
|
||||
}
|
||||
|
||||
if (!tags.contains(lastSelectedParent->tag())) {
|
||||
QPointF p = lastSelectedParent->sceneBoundingRect().topLeft();
|
||||
if (tags.isEmpty()) {
|
||||
pp = p;
|
||||
} else {
|
||||
pp.setX(qMin(pp.x(), p.x()));
|
||||
pp.setY(qMin(pp.y(), p.y()));
|
||||
}
|
||||
lastSelectedParent->updateUIProperties();
|
||||
tags << lastSelectedParent->tag();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minPos = pp;
|
||||
return tags;
|
||||
}
|
||||
|
||||
QVector<ScxmlTag*> findRemovedTags(const QVector<BaseItem*> &items)
|
||||
{
|
||||
// Find right tags
|
||||
QVector<ScxmlTag*> tags;
|
||||
foreach (BaseItem *it, items) {
|
||||
if (it->isSelected()) {
|
||||
// Find the last selected parent
|
||||
BaseItem *parent = it->parentBaseItem();
|
||||
BaseItem *lastSelectedParent = it;
|
||||
while (parent != 0) {
|
||||
if (parent->isSelected())
|
||||
lastSelectedParent = parent;
|
||||
parent = parent->parentBaseItem();
|
||||
}
|
||||
|
||||
// Add tag to the list
|
||||
if (!tags.contains(lastSelectedParent->tag()))
|
||||
tags << lastSelectedParent->tag();
|
||||
}
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
void layout(const QList<QGraphicsItem*> &items)
|
||||
{
|
||||
// Collect child items
|
||||
QList<ConnectableItem*> childItems;
|
||||
ConnectableItem *initialItem = nullptr;
|
||||
ConnectableItem *finalItem = nullptr;
|
||||
foreach (QGraphicsItem *item, items) {
|
||||
auto connectableItem = qgraphicsitem_cast<ConnectableItem*>(item);
|
||||
if (connectableItem) {
|
||||
if (connectableItem->type() == InitialStateType)
|
||||
initialItem = connectableItem;
|
||||
else if (connectableItem->type() == FinalStateType)
|
||||
finalItem = connectableItem;
|
||||
else if (connectableItem->type() >= HistoryType)
|
||||
childItems << connectableItem;
|
||||
}
|
||||
}
|
||||
|
||||
// Change initial-item position
|
||||
ConnectableItem *firstItem = nullptr;
|
||||
if (initialItem && initialItem->outputTransitionCount() == 1) {
|
||||
firstItem = initialItem->outputTransitions()[0]->connectedItem(initialItem);
|
||||
int index = childItems.indexOf(firstItem);
|
||||
if (index > 0)
|
||||
childItems.swap(index, 0);
|
||||
}
|
||||
|
||||
// Search final-item
|
||||
ConnectableItem *lastItem = nullptr;
|
||||
if (finalItem && finalItem->inputTransitionCount() > 0)
|
||||
lastItem = finalItem->inputTransitions()[0]->connectedItem(finalItem);
|
||||
|
||||
int startAngle = qrand() % 2 == 0 ? 180 : 90;
|
||||
int startDistance = 40 + childItems.count() * 10;
|
||||
if (childItems.count() > 0) {
|
||||
// Init position of the items
|
||||
int angleDiff = 360 / (childItems.count() + 1);
|
||||
for (int i = 0; i < childItems.count(); ++i) {
|
||||
int angle = startAngle + i * angleDiff;
|
||||
QLineF line = QLineF::fromPolar(startDistance, angle);
|
||||
childItems[i]->setPos(line.p2());
|
||||
}
|
||||
|
||||
// Then grow the distances so much that there is no any overlapped items
|
||||
for (int i = 0; i < childItems.count(); ++i) {
|
||||
int angle = startAngle + i * angleDiff;
|
||||
QLineF line = QLineF::fromPolar(startDistance, angle);
|
||||
ConnectableItem *movingItem = childItems[i];
|
||||
QRectF r2 = movingItem->boundingRect();
|
||||
r2.moveTopLeft(r2.topLeft() + movingItem->pos());
|
||||
|
||||
bool intersects = true;
|
||||
|
||||
while (intersects) {
|
||||
intersects = false;
|
||||
for (int j = 0; j < childItems.count(); ++j) {
|
||||
if (j != i) {
|
||||
QRectF r1 = childItems[j]->boundingRect();
|
||||
r1.moveTopLeft(r1.topLeft() + childItems[j]->pos());
|
||||
|
||||
if (r2.intersects(r1)) {
|
||||
intersects = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (intersects) {
|
||||
line.setLength(line.length() + 50);
|
||||
movingItem->setPos(line.p2());
|
||||
r2 = movingItem->boundingRect();
|
||||
r2.moveTopLeft(r2.topLeft() + movingItem->pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then decrease the distances so much as possible
|
||||
for (int i = 0; i < childItems.count(); ++i) {
|
||||
ConnectableItem *movingItem = childItems[i];
|
||||
QPointF p = movingItem->pos();
|
||||
QLineF line(QPointF(0, 0), p);
|
||||
QRectF r2 = movingItem->boundingRect();
|
||||
r2.moveTopLeft(r2.topLeft() + p);
|
||||
|
||||
bool cont = true;
|
||||
while (cont) {
|
||||
bool intersects = false;
|
||||
for (int j = 0; j < childItems.count(); ++j) {
|
||||
if (j != i) {
|
||||
QRectF r1 = childItems[j]->boundingRect();
|
||||
r1.moveTopLeft(r1.topLeft() + childItems[j]->pos());
|
||||
|
||||
if (r2.intersects(r1)) {
|
||||
intersects = true;
|
||||
cont = false;
|
||||
line.setLength(line.length() + 20);
|
||||
movingItem->setPos(line.p2());
|
||||
r2 = movingItem->boundingRect();
|
||||
r2.moveTopLeft(r2.topLeft() + movingItem->pos());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!intersects) {
|
||||
line.setLength(line.length() - 20);
|
||||
movingItem->setPos(line.p2());
|
||||
r2 = movingItem->boundingRect();
|
||||
r2.moveTopLeft(r2.topLeft() + movingItem->pos());
|
||||
if (line.length() < 100)
|
||||
cont = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally set initial and final positions
|
||||
foreach (ConnectableItem *item, childItems) {
|
||||
if (item == firstItem)
|
||||
initialItem->setPos(firstItem->pos() + firstItem->boundingRect().topLeft() - QPointF(50, 50));
|
||||
else if (item == lastItem) {
|
||||
int angle = startAngle + childItems.indexOf(item) * angleDiff;
|
||||
QLineF line = QLineF::fromPolar(qMax(lastItem->boundingRect().width() / 2, lastItem->boundingRect().height() / 2) + 20, angle);
|
||||
finalItem->setPos(lastItem->pos() + lastItem->boundingRect().center() + line.p2());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isChild(const QGraphicsItem *parent, const QGraphicsItem *child)
|
||||
{
|
||||
while (child != 0) {
|
||||
if (parent == child)
|
||||
return true;
|
||||
child = child->parentItem();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSomeSelected(QGraphicsItem *item)
|
||||
{
|
||||
while (item != 0) {
|
||||
if (item->isSelected())
|
||||
return true;
|
||||
item = item->parentItem();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void moveTop(BaseItem *item, GraphicsScene *scene)
|
||||
{
|
||||
if (item && scene) {
|
||||
// Make the current item to the topmost of all
|
||||
QGraphicsItem *parentItem = item->parentItem();
|
||||
QList<QGraphicsItem*> children;
|
||||
if (parentItem)
|
||||
children = parentItem->childItems();
|
||||
else
|
||||
children = scene->sceneItems(Qt::DescendingOrder);
|
||||
|
||||
// Remove unnecessary items
|
||||
for (int i = children.count(); i--;) {
|
||||
if (children[i]->type() < InitialStateType)
|
||||
children.takeAt(i);
|
||||
}
|
||||
|
||||
// Change stack order
|
||||
const int ind = parentItem ? children.indexOf(item) : 0;
|
||||
for (int i = ind; i < children.count(); ++i)
|
||||
children[i]->stackBefore(item);
|
||||
}
|
||||
}
|
||||
|
||||
ScxmlTag *addNewTag(ScxmlTag *parent, TagType type, GraphicsScene *scene)
|
||||
{
|
||||
if (parent) {
|
||||
ScxmlDocument *document = parent->document();
|
||||
auto newTag = new ScxmlTag(type, document);
|
||||
document->addTag(parent, newTag);
|
||||
|
||||
if (scene)
|
||||
scene->unselectAll();
|
||||
|
||||
document->setCurrentTag(newTag);
|
||||
return newTag;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScxmlTag *addChild(ScxmlTag *tag, const QVariantMap &data, GraphicsScene *scene)
|
||||
{
|
||||
TagType newTagType = (TagType)data.value(Constants::C_SCXMLTAG_TAGTYPE, 0).toInt();
|
||||
TagType subMenuTagType = (TagType)data.value(Constants::C_SCXMLTAG_PARENTTAG, 0).toInt();
|
||||
if (newTagType >= UnknownTag) {
|
||||
// Check if we must create or add submenu
|
||||
if (subMenuTagType > UnknownTag && subMenuTagType != tag->tagType()) {
|
||||
// Check if submenu-tag is already available
|
||||
ScxmlTag *subMenuTag = TagUtils::findChild(tag, subMenuTagType);
|
||||
if (subMenuTag)
|
||||
return addNewTag(subMenuTag, newTagType, scene);
|
||||
else {
|
||||
// If dont, create new submenutag and add new child
|
||||
subMenuTag = addNewTag(tag, subMenuTagType, scene);
|
||||
return addNewTag(subMenuTag, newTagType, scene);
|
||||
}
|
||||
} else
|
||||
return addNewTag(tag, newTagType, scene);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace SceneUtils
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
90
src/plugins/scxmleditor/plugin_interface/sceneutils.h
Normal file
90
src/plugins/scxmleditor/plugin_interface/sceneutils.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
|
||||
#include <QGraphicsScene>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QGraphicsItem)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class GraphicsScene;
|
||||
class ConnectableItem;
|
||||
class InitialStateItem;
|
||||
class BaseItem;
|
||||
class ScxmlTag;
|
||||
|
||||
/**
|
||||
* Namespace SceneUtils includes some usable function to manipulate the data of the items.
|
||||
*/
|
||||
namespace SceneUtils {
|
||||
|
||||
ScxmlTag *addChild(ScxmlTag *tag, const QVariantMap &data, GraphicsScene *scene);
|
||||
ScxmlTag *addNewTag(ScxmlTag *parent, TagType type, GraphicsScene *scene);
|
||||
ConnectableItem *createItem(ItemType type, const QPointF &pos = QPointF());
|
||||
ConnectableItem *createItemByTagType(TagType type, const QPointF &pos = QPointF());
|
||||
ScxmlTag *createTag(ItemType type, ScxmlDocument *document);
|
||||
bool canDrop(int parentType, int childType);
|
||||
QVector<ScxmlTag*> findCopyTags(const QVector<BaseItem*> &items, QPointF &minPos);
|
||||
QVector<ScxmlTag*> findRemovedTags(const QVector<BaseItem*> &items);
|
||||
void layout(const QList<QGraphicsItem*> &items);
|
||||
bool isSomeSelected(QGraphicsItem *item);
|
||||
void moveTop(BaseItem *item, GraphicsScene *scene);
|
||||
|
||||
bool isChild(const QGraphicsItem *parent, const QGraphicsItem *child);
|
||||
|
||||
template <class T>
|
||||
bool hasSiblingStates(T *item)
|
||||
{
|
||||
if (item) {
|
||||
QList<QGraphicsItem*> children;
|
||||
QGraphicsItem *parentItem = item->parentItem();
|
||||
if (parentItem) {
|
||||
children = parentItem->childItems();
|
||||
} else if (item->scene()) {
|
||||
foreach (QGraphicsItem *it, item->scene()->items()) {
|
||||
if (!it->parentItem())
|
||||
children << it;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (QGraphicsItem *it, children) {
|
||||
if (it != item && it->type() == item->type()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace SceneUtils
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scgraphicsitemprovider.h"
|
||||
#include "idwarningitem.h"
|
||||
#include "initialstateitem.h"
|
||||
#include "initialwarningitem.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "stateitem.h"
|
||||
#include "transitionitem.h"
|
||||
#include "transitionwarningitem.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
SCGraphicsItemProvider::SCGraphicsItemProvider(QObject *parent)
|
||||
: GraphicsItemProvider(parent)
|
||||
{
|
||||
}
|
||||
|
||||
WarningItem *SCGraphicsItemProvider::createWarningItem(const QString &key, BaseItem *parentItem) const
|
||||
{
|
||||
if (key == Constants::C_STATE_WARNING_ID && parentItem)
|
||||
return new IdWarningItem(parentItem);
|
||||
|
||||
if (key == Constants::C_STATE_WARNING_TRANSITION && parentItem && parentItem->type() == TransitionType)
|
||||
return new TransitionWarningItem(static_cast<TransitionItem*>(parentItem));
|
||||
|
||||
if (key == Constants::C_STATE_WARNING_INITIAL && parentItem && parentItem->type() == InitialStateType)
|
||||
return new InitialWarningItem(static_cast<InitialStateItem*>(parentItem));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "graphicsitemprovider.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class SCGraphicsItemProvider : public GraphicsItemProvider
|
||||
{
|
||||
public:
|
||||
SCGraphicsItemProvider(QObject *parent = nullptr);
|
||||
|
||||
WarningItem *createWarningItem(const QString &key, BaseItem *parentItem) const override;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
181
src/plugins/scxmleditor/plugin_interface/scshapeprovider.cpp
Normal file
181
src/plugins/scxmleditor/plugin_interface/scshapeprovider.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scshapeprovider.h"
|
||||
#include "scxmltag.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
SCShapeProvider::SCShapeProvider(QObject *parent)
|
||||
: ShapeProvider(parent)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
SCShapeProvider::~SCShapeProvider()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void SCShapeProvider::clear()
|
||||
{
|
||||
qDeleteAll(m_groups);
|
||||
m_groups.clear();
|
||||
}
|
||||
|
||||
void SCShapeProvider::initGroups()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void SCShapeProvider::init()
|
||||
{
|
||||
ShapeGroup *group = addGroup(tr("Common States"));
|
||||
group->addShape(createShape(tr("Initial"), QIcon(":/scxmleditor/images/initial.png"), QStringList() << "scxml"
|
||||
<< "state"
|
||||
<< "parallel",
|
||||
"<initial/>"));
|
||||
group->addShape(createShape(tr("Final"), QIcon(":/scxmleditor/images/final.png"), QStringList() << "scxml"
|
||||
<< "state"
|
||||
<< "parallel",
|
||||
"<final/>"));
|
||||
group->addShape(createShape(tr("State"), QIcon(":/scxmleditor/images/state.png"), QStringList() << "scxml"
|
||||
<< "state"
|
||||
<< "parallel",
|
||||
"<state/>"));
|
||||
group->addShape(createShape(tr("Parallel"), QIcon(":/scxmleditor/images/parallel.png"), QStringList() << "scxml"
|
||||
<< "state"
|
||||
<< "parallel",
|
||||
"<parallel/>"));
|
||||
group->addShape(createShape(tr("History"), QIcon(":/scxmleditor/images/history.png"), QStringList() << "state"
|
||||
<< "parallel",
|
||||
"<history/>"));
|
||||
}
|
||||
|
||||
ShapeProvider::Shape *SCShapeProvider::shape(int groupIndex, int shapeIndex)
|
||||
{
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count()) {
|
||||
if (shapeIndex >= 0 && shapeIndex < m_groups[groupIndex]->shapes.count())
|
||||
return m_groups[groupIndex]->shapes[shapeIndex];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ShapeProvider::ShapeGroup *SCShapeProvider::group(int groupIndex)
|
||||
{
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count())
|
||||
return m_groups[groupIndex];
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SCShapeProvider::ShapeGroup *SCShapeProvider::addGroup(const QString &title)
|
||||
{
|
||||
auto group = new ShapeGroup;
|
||||
group->title = title;
|
||||
m_groups << group;
|
||||
return group;
|
||||
}
|
||||
|
||||
SCShapeProvider::Shape *SCShapeProvider::createShape(const QString &title, const QIcon &icon, const QStringList &filters, const QByteArray &scxmlData, const QVariant &userData)
|
||||
{
|
||||
auto shape = new Shape;
|
||||
shape->title = title;
|
||||
shape->icon = icon;
|
||||
shape->filters = filters;
|
||||
shape->scxmlData = scxmlData;
|
||||
shape->userData = userData;
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
int SCShapeProvider::groupCount() const
|
||||
{
|
||||
return m_groups.count();
|
||||
}
|
||||
|
||||
QString SCShapeProvider::groupTitle(int groupIndex) const
|
||||
{
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count())
|
||||
return m_groups[groupIndex]->title;
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
int SCShapeProvider::shapeCount(int groupIndex) const
|
||||
{
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count())
|
||||
return m_groups[groupIndex]->shapes.count();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString SCShapeProvider::shapeTitle(int groupIndex, int shapeIndex) const
|
||||
{
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count()) {
|
||||
if (shapeIndex >= 0 && shapeIndex < m_groups[groupIndex]->shapes.count())
|
||||
return m_groups[groupIndex]->shapes[shapeIndex]->title;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QIcon SCShapeProvider::shapeIcon(int groupIndex, int shapeIndex) const
|
||||
{
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count()) {
|
||||
if (shapeIndex >= 0 && shapeIndex < m_groups[groupIndex]->shapes.count())
|
||||
return m_groups[groupIndex]->shapes[shapeIndex]->icon;
|
||||
}
|
||||
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
bool SCShapeProvider::canDrop(int groupIndex, int shapeIndex, ScxmlTag *parent) const
|
||||
{
|
||||
QString tagName = parent ? parent->tagName(false) : "scxml";
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count()) {
|
||||
if (shapeIndex >= 0 && shapeIndex < m_groups[groupIndex]->shapes.count()) {
|
||||
const QStringList &filters = m_groups[groupIndex]->shapes[shapeIndex]->filters;
|
||||
return filters.isEmpty() || filters.contains(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray SCShapeProvider::scxmlCode(int groupIndex, int shapeIndex, ScxmlTag *parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
|
||||
if (groupIndex >= 0 && groupIndex < m_groups.count()) {
|
||||
if (shapeIndex >= 0 && shapeIndex < m_groups[groupIndex]->shapes.count())
|
||||
return m_groups[groupIndex]->shapes[shapeIndex]->scxmlData;
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
68
src/plugins/scxmleditor/plugin_interface/scshapeprovider.h
Normal file
68
src/plugins/scxmleditor/plugin_interface/scshapeprovider.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shapeprovider.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlTag;
|
||||
|
||||
class SCShapeProvider : public ShapeProvider
|
||||
{
|
||||
public:
|
||||
SCShapeProvider(QObject *parent = nullptr);
|
||||
~SCShapeProvider() override;
|
||||
|
||||
int groupCount() const override;
|
||||
QString groupTitle(int groupIndex) const override;
|
||||
|
||||
int shapeCount(int groupIndex) const override;
|
||||
QString shapeTitle(int groupIndex, int shapeIndex) const override;
|
||||
QIcon shapeIcon(int groupIndex, int shapeIndex) const override;
|
||||
|
||||
bool canDrop(int groupIndex, int shapeIndex, ScxmlTag *parent) const override;
|
||||
QByteArray scxmlCode(int groupIndex, int shapeIndex, ScxmlTag *parent) const override;
|
||||
|
||||
protected:
|
||||
virtual void clear();
|
||||
virtual void initGroups();
|
||||
virtual ShapeGroup *addGroup(const QString &title);
|
||||
virtual Shape *createShape(const QString &title, const QIcon &icon, const QStringList &filters, const QByteArray &scxmlData, const QVariant &userData = QVariant());
|
||||
Shape *shape(int groupIndex, int shapeIndex);
|
||||
ShapeGroup *group(int groupIndex);
|
||||
|
||||
private:
|
||||
void init();
|
||||
QVector<ShapeGroup*> m_groups;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
87
src/plugins/scxmleditor/plugin_interface/scutilsprovider.cpp
Normal file
87
src/plugins/scxmleditor/plugin_interface/scutilsprovider.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scutilsprovider.h"
|
||||
#include "mytypes.h"
|
||||
#include "scxmltag.h"
|
||||
#include "stateitem.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
SCUtilsProvider::SCUtilsProvider(QObject *parent)
|
||||
: UtilsProvider(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void SCUtilsProvider::checkInitialState(const QList<QGraphicsItem*> &items, ScxmlTag *parentTag)
|
||||
{
|
||||
ScxmlTag *initialStateTag = nullptr;
|
||||
|
||||
if (parentTag) {
|
||||
|
||||
// 1. If we have initial-state, we must use it as init-state
|
||||
if (parentTag->hasChild(Initial)) {
|
||||
parentTag->setAttribute("initial", QString());
|
||||
} else {
|
||||
QString id = parentTag->attribute("initial");
|
||||
|
||||
// 2. If no initial-state available, try to find state with initial-attribute
|
||||
if (!id.isEmpty()) {
|
||||
// Find state with id
|
||||
for (int i = 0; i < parentTag->childCount(); ++i) {
|
||||
ScxmlTag *child = parentTag->child(i);
|
||||
if ((child->tagType() == State || child->tagType() == Parallel)
|
||||
&& child->attribute("id", true) == id) {
|
||||
initialStateTag = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!initialStateTag)
|
||||
parentTag->setAttribute("initial", QString());
|
||||
}
|
||||
|
||||
// 3. If we still cant find initial-state, we must select first
|
||||
if (!initialStateTag) {
|
||||
// Search first state
|
||||
for (int i = 0; i < parentTag->childCount(); ++i) {
|
||||
ScxmlTag *child = parentTag->child(i);
|
||||
if (child->tagType() == State || child->tagType() == Parallel) {
|
||||
initialStateTag = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (QGraphicsItem *item, items) {
|
||||
if (item->type() >= StateType) {
|
||||
auto stateItem = static_cast<StateItem*>(item);
|
||||
if (stateItem)
|
||||
stateItem->setInitial(stateItem->tag() == initialStateTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
45
src/plugins/scxmleditor/plugin_interface/scutilsprovider.h
Normal file
45
src/plugins/scxmleditor/plugin_interface/scutilsprovider.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utilsprovider.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlTag;
|
||||
|
||||
class SCUtilsProvider : public UtilsProvider
|
||||
{
|
||||
public:
|
||||
SCUtilsProvider(QObject *parent = nullptr);
|
||||
|
||||
void checkInitialState(const QList<QGraphicsItem*> &items, ScxmlTag *parentTag) override;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
701
src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp
Normal file
701
src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp
Normal file
@@ -0,0 +1,701 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmlnamespace.h"
|
||||
#include "scxmltagutils.h"
|
||||
#include "undocommands.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
#include <app/app_version.h>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ScxmlDocument::ScxmlDocument(const QString &fileName, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
initVariables();
|
||||
m_fileName = fileName;
|
||||
load(fileName);
|
||||
}
|
||||
|
||||
ScxmlDocument::ScxmlDocument(const QByteArray &data, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
initVariables();
|
||||
load(QLatin1String(data));
|
||||
}
|
||||
|
||||
ScxmlDocument::~ScxmlDocument()
|
||||
{
|
||||
clear(false);
|
||||
}
|
||||
|
||||
void ScxmlDocument::initVariables()
|
||||
{
|
||||
m_idDelimiter = "::";
|
||||
m_undoStack = new QUndoStack(this);
|
||||
connect(m_undoStack, &QUndoStack::cleanChanged, this, &ScxmlDocument::documentChanged);
|
||||
}
|
||||
|
||||
void ScxmlDocument::clear(bool createRoot)
|
||||
{
|
||||
m_currentTag = nullptr;
|
||||
m_nextIdHash.clear();
|
||||
|
||||
// First clear undostack
|
||||
m_undoStack->clear();
|
||||
|
||||
// Second delete all other available tags
|
||||
// tags will call the removeChild-function -> m_tags will be cleared
|
||||
for (int i = m_tags.count(); i--;)
|
||||
delete m_tags[i];
|
||||
|
||||
m_rootTags.clear();
|
||||
clearNamespaces();
|
||||
|
||||
if (createRoot) {
|
||||
pushRootTag(createScxmlTag());
|
||||
rootTag()->setAttribute("qt:editorversion", QLatin1String(Core::Constants::IDE_VERSION_LONG));
|
||||
|
||||
auto ns = new ScxmlNamespace("qt", "http://www.qt.io/2015/02/scxml-ext");
|
||||
ns->setTagVisibility("editorInfo", false);
|
||||
addNamespace(ns);
|
||||
}
|
||||
|
||||
m_useFullNameSpace = false;
|
||||
}
|
||||
|
||||
QString ScxmlDocument::nameSpaceDelimiter() const
|
||||
{
|
||||
return m_idDelimiter;
|
||||
}
|
||||
|
||||
bool ScxmlDocument::useFullNameSpace() const
|
||||
{
|
||||
return m_useFullNameSpace;
|
||||
}
|
||||
|
||||
void ScxmlDocument::setNameSpaceDelimiter(const QString &delimiter)
|
||||
{
|
||||
m_idDelimiter = delimiter;
|
||||
}
|
||||
|
||||
QString ScxmlDocument::fileName() const
|
||||
{
|
||||
return m_fileName;
|
||||
}
|
||||
|
||||
void ScxmlDocument::setFileName(const QString &filename)
|
||||
{
|
||||
m_fileName = filename;
|
||||
}
|
||||
|
||||
ScxmlNamespace *ScxmlDocument::scxmlNamespace(const QString &prefix)
|
||||
{
|
||||
return m_namespaces.value(prefix, 0);
|
||||
}
|
||||
|
||||
void ScxmlDocument::addNamespace(ScxmlNamespace *ns)
|
||||
{
|
||||
if (!ns)
|
||||
return;
|
||||
|
||||
delete m_namespaces.take(ns->prefix());
|
||||
m_namespaces[ns->prefix()] = ns;
|
||||
|
||||
ScxmlTag *scxmlTag = scxmlRootTag();
|
||||
if (scxmlTag) {
|
||||
QMapIterator<QString, ScxmlNamespace*> i(m_namespaces);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
QString prefix = i.value()->prefix();
|
||||
if (prefix.isEmpty())
|
||||
prefix = "xmlns";
|
||||
|
||||
if (prefix.startsWith("xmlns"))
|
||||
scxmlTag->setAttribute(prefix, i.value()->name());
|
||||
else
|
||||
scxmlTag->setAttribute(QString::fromLatin1("xmlns:%1").arg(prefix), i.value()->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlDocument::clearNamespaces()
|
||||
{
|
||||
while (!m_namespaces.isEmpty()) {
|
||||
delete m_namespaces.take(m_namespaces.firstKey());
|
||||
}
|
||||
}
|
||||
|
||||
bool ScxmlDocument::generateSCXML(QIODevice *io, ScxmlTag *tag) const
|
||||
{
|
||||
QXmlStreamWriter xml(io);
|
||||
xml.setAutoFormatting(true);
|
||||
xml.writeStartDocument();
|
||||
if (tag)
|
||||
tag->writeXml(xml);
|
||||
else
|
||||
rootTag()->writeXml(xml);
|
||||
xml.writeEndDocument();
|
||||
|
||||
return !xml.hasError();
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlDocument::createScxmlTag()
|
||||
{
|
||||
auto tag = new ScxmlTag(Scxml, this);
|
||||
QMapIterator<QString, ScxmlNamespace*> i(m_namespaces);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
QString prefix = i.value()->prefix();
|
||||
if (prefix.isEmpty())
|
||||
prefix = "xmlns";
|
||||
|
||||
if (prefix.startsWith("xmlns"))
|
||||
tag->setAttribute(prefix, i.value()->name());
|
||||
else
|
||||
tag->setAttribute(QString::fromLatin1("xmlns:%1").arg(prefix), i.value()->name());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
bool ScxmlDocument::hasLayouted() const
|
||||
{
|
||||
return m_hasLayouted;
|
||||
}
|
||||
QColor ScxmlDocument::getColor(int depth) const
|
||||
{
|
||||
return m_colors.isEmpty() ? QColor(Qt::gray) : m_colors[depth % m_colors.count()];
|
||||
}
|
||||
|
||||
void ScxmlDocument::setLevelColors(const QVector<QColor> &colors)
|
||||
{
|
||||
m_colors = colors;
|
||||
emit colorThemeChanged();
|
||||
}
|
||||
|
||||
bool ScxmlDocument::load(QIODevice *io)
|
||||
{
|
||||
m_currentTag = nullptr;
|
||||
clearNamespaces();
|
||||
|
||||
bool ok = true;
|
||||
clear(false);
|
||||
|
||||
QXmlStreamReader xml(io);
|
||||
while (!xml.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = xml.readNext();
|
||||
|
||||
if (token == QXmlStreamReader::StartDocument)
|
||||
continue;
|
||||
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (xml.name() == "scxml") {
|
||||
// Get and add namespaces
|
||||
QXmlStreamNamespaceDeclarations ns = xml.namespaceDeclarations();
|
||||
for (int i = 0; i < ns.count(); ++i)
|
||||
addNamespace(new ScxmlNamespace(ns[i].prefix().toString(), ns[i].namespaceUri().toString()));
|
||||
|
||||
// create root tag
|
||||
pushRootTag(createScxmlTag());
|
||||
|
||||
// and read other tags also
|
||||
rootTag()->readXml(xml);
|
||||
|
||||
// Check editorversion
|
||||
m_hasLayouted = rootTag()->hasAttribute("qt:editorversion");
|
||||
rootTag()->setAttribute("qt:editorversion", QLatin1String(Core::Constants::IDE_VERSION_LONG));
|
||||
}
|
||||
}
|
||||
|
||||
if (token == QXmlStreamReader::Invalid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (xml.hasError()) {
|
||||
m_hasError = true;
|
||||
initErrorMessage(xml, io);
|
||||
m_fileName.clear();
|
||||
ok = false;
|
||||
|
||||
clear();
|
||||
} else {
|
||||
m_hasError = false;
|
||||
m_lastError.clear();
|
||||
}
|
||||
|
||||
m_undoStack->setClean();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void ScxmlDocument::initErrorMessage(const QXmlStreamReader &xml, QIODevice *io)
|
||||
{
|
||||
QString errorString;
|
||||
switch (xml.error()) {
|
||||
case QXmlStreamReader::Error::UnexpectedElementError:
|
||||
errorString = tr("UnexpectedElementError");
|
||||
break;
|
||||
case QXmlStreamReader::Error::NotWellFormedError:
|
||||
errorString = tr("NotWellFormedError");
|
||||
break;
|
||||
case QXmlStreamReader::Error::PrematureEndOfDocumentError:
|
||||
errorString = tr("PrematureEndOfDocumentError");
|
||||
break;
|
||||
case QXmlStreamReader::Error::CustomError:
|
||||
errorString = tr("CustomError");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QString lineString;
|
||||
io->seek(0);
|
||||
for (int i = 0; i < xml.lineNumber() - 1; ++i)
|
||||
io->readLine();
|
||||
lineString = QLatin1String(io->readLine());
|
||||
|
||||
m_lastError = tr("Error in reading XML.\nType: %1 (%2)\nDescription: %3\n\nRow: %4, Column: %5\n%6")
|
||||
.arg(xml.error())
|
||||
.arg(errorString)
|
||||
.arg(xml.errorString())
|
||||
.arg(xml.lineNumber())
|
||||
.arg(xml.columnNumber())
|
||||
.arg(lineString);
|
||||
}
|
||||
|
||||
bool ScxmlDocument::pasteData(const QByteArray &data, const QPointF &minPos, const QPointF &pastePos)
|
||||
{
|
||||
if (!m_currentTag)
|
||||
m_currentTag = rootTag();
|
||||
|
||||
if (!m_currentTag) {
|
||||
m_hasError = true;
|
||||
m_lastError = tr("Current tag not selected");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data.trimmed().isEmpty()) {
|
||||
m_hasError = true;
|
||||
m_lastError = tr("Pasted data is empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
m_undoStack->beginMacro(tr("Paste item(s)"));
|
||||
|
||||
QByteArray d(data);
|
||||
QBuffer buffer(&d);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QXmlStreamReader xml(&buffer);
|
||||
foreach (ScxmlNamespace *ns, m_namespaces) {
|
||||
xml.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration(ns->prefix(), ns->name()));
|
||||
}
|
||||
|
||||
m_idMap.clear();
|
||||
QVector<ScxmlTag*> addedTags;
|
||||
|
||||
while (!xml.atEnd()) {
|
||||
QXmlStreamReader::TokenType token = xml.readNext();
|
||||
|
||||
if (token == QXmlStreamReader::StartDocument)
|
||||
continue;
|
||||
|
||||
if (token == QXmlStreamReader::StartElement) {
|
||||
if (xml.name().toString() == "scxml")
|
||||
continue;
|
||||
|
||||
ScxmlTag *childTag = nullptr;
|
||||
if ((m_currentTag->tagType() == Initial || m_currentTag->tagType() == History) && xml.name().toString() == "transition")
|
||||
childTag = new ScxmlTag(InitialTransition, this);
|
||||
else
|
||||
childTag = new ScxmlTag(xml.prefix().toString(), xml.name().toString(), this);
|
||||
|
||||
childTag->readXml(xml, true);
|
||||
addedTags << childTag;
|
||||
}
|
||||
|
||||
if (token == QXmlStreamReader::Invalid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (xml.error()) {
|
||||
m_hasError = true;
|
||||
qDeleteAll(addedTags);
|
||||
addedTags.clear();
|
||||
initErrorMessage(xml, &buffer);
|
||||
ok = false;
|
||||
} else {
|
||||
m_hasError = false;
|
||||
m_lastError.clear();
|
||||
|
||||
// Fine-tune names and coordinates
|
||||
for (int i = 0; i < addedTags.count(); ++i)
|
||||
TagUtils::modifyPosition(addedTags[i], minPos, pastePos);
|
||||
|
||||
// Update targets and initial-attributes
|
||||
for (int i = 0; i < addedTags.count(); ++i)
|
||||
addedTags[i]->finalizeTagNames();
|
||||
|
||||
// Add tags to the document
|
||||
addTags(m_currentTag, addedTags);
|
||||
}
|
||||
|
||||
m_undoStack->endMacro();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void ScxmlDocument::load(const QString &fileName)
|
||||
{
|
||||
if (QFile::exists(fileName)) {
|
||||
QFile file(fileName);
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
if (load(&file)) {
|
||||
m_fileName = fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If loading doesn't work, create root tag here
|
||||
if (m_rootTags.isEmpty()) {
|
||||
pushRootTag(createScxmlTag());
|
||||
rootTag()->setAttribute("qt:editorversion", QLatin1String(Core::Constants::IDE_VERSION_LONG));
|
||||
}
|
||||
|
||||
auto ns = new ScxmlNamespace("qt", "http://www.qt.io/2015/02/scxml-ext");
|
||||
ns->setTagVisibility("editorInfo", false);
|
||||
addNamespace(ns);
|
||||
}
|
||||
|
||||
void ScxmlDocument::printSCXML()
|
||||
{
|
||||
qDebug() << content();
|
||||
}
|
||||
|
||||
QByteArray ScxmlDocument::content(const QVector<ScxmlTag*> &tags) const
|
||||
{
|
||||
QByteArray result;
|
||||
if (tags.count() > 0) {
|
||||
QBuffer buffer(&result);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
|
||||
bool writeScxml = tags.count() > 1 || tags[0]->tagType() != Scxml;
|
||||
|
||||
QXmlStreamWriter xml(&buffer);
|
||||
xml.setAutoFormatting(true);
|
||||
xml.writeStartDocument();
|
||||
if (writeScxml)
|
||||
xml.writeStartElement("scxml");
|
||||
|
||||
foreach (ScxmlTag *tag, tags) {
|
||||
tag->writeXml(xml);
|
||||
}
|
||||
xml.writeEndDocument();
|
||||
|
||||
if (writeScxml)
|
||||
xml.writeEndElement();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray ScxmlDocument::content(ScxmlTag *tag) const
|
||||
{
|
||||
QByteArray byteArray;
|
||||
QBuffer buffer(&byteArray);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
generateSCXML(&buffer, tag);
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
bool ScxmlDocument::save()
|
||||
{
|
||||
return save(m_fileName);
|
||||
}
|
||||
|
||||
bool ScxmlDocument::save(const QString &fileName)
|
||||
{
|
||||
QString name(fileName);
|
||||
if (!name.endsWith(".scxml", Qt::CaseInsensitive))
|
||||
name.append(".scxml");
|
||||
|
||||
bool ok = true;
|
||||
|
||||
QFile file(name);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
ok = generateSCXML(&file, scxmlRootTag());
|
||||
if (ok) {
|
||||
m_fileName = name;
|
||||
m_undoStack->setClean();
|
||||
}
|
||||
file.close();
|
||||
if (!ok)
|
||||
m_lastError = tr("Cannot save xml to the file %1.").arg(fileName);
|
||||
} else {
|
||||
ok = false;
|
||||
m_lastError = tr("Cannot open file %1.").arg(fileName);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void ScxmlDocument::setContent(ScxmlTag *tag, const QString &content)
|
||||
{
|
||||
if (tag && !m_undoRedoRunning)
|
||||
m_undoStack->push(new SetContentCommand(this, tag, content));
|
||||
}
|
||||
|
||||
void ScxmlDocument::setValue(ScxmlTag *tag, const QString &key, const QString &value)
|
||||
{
|
||||
if (tag && !m_undoRedoRunning)
|
||||
m_undoStack->push(new SetAttributeCommand(this, tag, key, value));
|
||||
}
|
||||
|
||||
void ScxmlDocument::setValue(ScxmlTag *tag, int attributeIndex, const QString &value)
|
||||
{
|
||||
if (tag && attributeIndex >= 0 && attributeIndex < tag->info()->n_attributes)
|
||||
m_undoStack->push(new SetAttributeCommand(this, tag, QLatin1String(tag->info()->attributes[attributeIndex].name), value));
|
||||
}
|
||||
|
||||
void ScxmlDocument::setEditorInfo(ScxmlTag *tag, const QString &key, const QString &value)
|
||||
{
|
||||
if (tag && !m_undoRedoRunning)
|
||||
m_undoStack->push(new SetEditorInfoCommand(this, tag, key, value));
|
||||
}
|
||||
|
||||
void ScxmlDocument::setCurrentTag(ScxmlTag *tag)
|
||||
{
|
||||
if (tag != m_currentTag) {
|
||||
emit beginTagChange(TagCurrentChanged, tag, QVariant());
|
||||
m_currentTag = tag;
|
||||
emit endTagChange(TagCurrentChanged, tag, QVariant());
|
||||
}
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlDocument::currentTag() const
|
||||
{
|
||||
return m_currentTag;
|
||||
}
|
||||
|
||||
void ScxmlDocument::changeParent(ScxmlTag *child, ScxmlTag *newParent, int tagIndex)
|
||||
{
|
||||
if (child && child->parentTag() != newParent && !m_undoRedoRunning)
|
||||
m_undoStack->push(new ChangeParentCommand(this, child, newParent == nullptr ? rootTag() : newParent, tagIndex));
|
||||
}
|
||||
|
||||
void ScxmlDocument::changeOrder(ScxmlTag *child, int newPos)
|
||||
{
|
||||
if (child && !m_undoRedoRunning) {
|
||||
ScxmlTag *parentTag = child->parentTag();
|
||||
if (parentTag) {
|
||||
m_undoStack->push(new ChangeOrderCommand(this, child, parentTag, newPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlDocument::addTags(ScxmlTag *parent, const QVector<ScxmlTag*> tags)
|
||||
{
|
||||
if (m_undoRedoRunning)
|
||||
return;
|
||||
|
||||
if (!parent)
|
||||
parent = rootTag();
|
||||
|
||||
m_undoStack->push(new AddRemoveTagsBeginCommand(this, parent));
|
||||
for (int i = 0; i < tags.count(); ++i)
|
||||
addTag(parent, tags[i]);
|
||||
m_undoStack->push(new AddRemoveTagsEndCommand(this, parent));
|
||||
}
|
||||
|
||||
void ScxmlDocument::addTag(ScxmlTag *parent, ScxmlTag *child)
|
||||
{
|
||||
if (m_undoRedoRunning)
|
||||
return;
|
||||
|
||||
if (!parent)
|
||||
parent = rootTag();
|
||||
|
||||
if (parent && child) {
|
||||
m_undoStack->beginMacro(tr("Add Tag"));
|
||||
addTagRecursive(parent, child);
|
||||
m_undoStack->endMacro();
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlDocument::removeTag(ScxmlTag *tag)
|
||||
{
|
||||
if (tag && !m_undoRedoRunning) {
|
||||
// Create undo/redo -macro, because state can includes lot of child-states
|
||||
m_undoStack->beginMacro(tr("Remove Tag"));
|
||||
removeTagRecursive(tag);
|
||||
m_undoStack->endMacro();
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlDocument::addTagRecursive(ScxmlTag *parent, ScxmlTag *tag)
|
||||
{
|
||||
if (tag && !m_undoRedoRunning) {
|
||||
m_undoStack->push(new AddRemoveTagCommand(this, parent, tag, TagAddChild));
|
||||
|
||||
// First create AddRemoveTagCommands for the all children recursive
|
||||
for (int i = 0; i < tag->childCount(); ++i)
|
||||
addTagRecursive(tag, tag->child(i));
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlDocument::removeTagRecursive(ScxmlTag *tag)
|
||||
{
|
||||
if (tag && !m_undoRedoRunning) {
|
||||
// First create AddRemoveTagCommands for the all children recursive
|
||||
int childCount = tag->childCount();
|
||||
for (int i = childCount; i--;)
|
||||
removeTagRecursive(tag->child(i));
|
||||
|
||||
m_undoStack->push(new AddRemoveTagCommand(this, tag->parentTag(), tag, TagRemoveChild));
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlDocument::setUseFullNameSpace(bool use)
|
||||
{
|
||||
if (m_useFullNameSpace != use)
|
||||
m_undoStack->push(new ChangeFullNameSpaceCommand(this, scxmlRootTag(), use));
|
||||
}
|
||||
|
||||
QString ScxmlDocument::nextUniqueId(const QString &key)
|
||||
{
|
||||
QString name;
|
||||
bool bFound = false;
|
||||
int id = 0;
|
||||
while (true) {
|
||||
id = m_nextIdHash.value(key, 0) + 1;
|
||||
m_nextIdHash[key] = id;
|
||||
bFound = false;
|
||||
name = QString::fromLatin1("%1_%2").arg(key).arg(id);
|
||||
|
||||
// Check duplicate
|
||||
foreach (const ScxmlTag *tag, m_tags) {
|
||||
if (tag->attribute("id") == name) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bFound)
|
||||
break;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
QString ScxmlDocument::getUniqueCopyId(const ScxmlTag *tag)
|
||||
{
|
||||
const QString key = tag->attribute("id");
|
||||
QString name = key;
|
||||
int counter = 1;
|
||||
bool bFound = false;
|
||||
|
||||
while (true) {
|
||||
bFound = false;
|
||||
// Check duplicate
|
||||
foreach (const ScxmlTag *t, m_tags) {
|
||||
if (t->attribute("id") == name && t != tag) {
|
||||
name = QString::fromLatin1("%1_Copy(%2)").arg(key).arg(counter);
|
||||
bFound = true;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
break;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
bool ScxmlDocument::changed() const
|
||||
{
|
||||
return !m_undoStack->isClean();
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlDocument::scxmlRootTag() const
|
||||
{
|
||||
ScxmlTag *tag = rootTag();
|
||||
while (tag && tag->tagType() != Scxml) {
|
||||
tag = tag->parentTag();
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlDocument::rootTag() const
|
||||
{
|
||||
return m_rootTags.isEmpty() ? 0 : m_rootTags.last();
|
||||
}
|
||||
|
||||
void ScxmlDocument::pushRootTag(ScxmlTag *tag)
|
||||
{
|
||||
m_rootTags << tag;
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlDocument::popRootTag()
|
||||
{
|
||||
return m_rootTags.takeLast();
|
||||
}
|
||||
|
||||
void ScxmlDocument::deleteRootTags()
|
||||
{
|
||||
while (m_rootTags.count() > 0)
|
||||
delete m_rootTags.takeLast();
|
||||
}
|
||||
|
||||
QUndoStack *ScxmlDocument::undoStack() const
|
||||
{
|
||||
return m_undoStack;
|
||||
}
|
||||
|
||||
void ScxmlDocument::addChild(ScxmlTag *tag)
|
||||
{
|
||||
if (!m_tags.contains(tag))
|
||||
m_tags << tag;
|
||||
}
|
||||
|
||||
void ScxmlDocument::removeChild(ScxmlTag *tag)
|
||||
{
|
||||
m_tags.removeAll(tag);
|
||||
}
|
||||
|
||||
void ScxmlDocument::setUndoRedoRunning(bool para)
|
||||
{
|
||||
m_undoRedoRunning = para;
|
||||
}
|
||||
|
||||
QFileInfo ScxmlDocument::qtBinDir() const
|
||||
{
|
||||
return m_qtBinDir;
|
||||
}
|
||||
296
src/plugins/scxmleditor/plugin_interface/scxmldocument.h
Normal file
296
src/plugins/scxmleditor/plugin_interface/scxmldocument.h
Normal file
@@ -0,0 +1,296 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QPointF>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QUndoStack)
|
||||
QT_FORWARD_DECLARE_CLASS(QXmlStreamReader)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlNamespace;
|
||||
class ScxmlTag;
|
||||
|
||||
/**
|
||||
* @brief The ScxmlDocument class represents an SCXML document.
|
||||
*
|
||||
* This is the root of the document tree, and provides the access to the document's data.
|
||||
* The tag-element is ScxmlTag. You can create ScxmlTag-objects outside this class, but you have to call data-manipulation
|
||||
* functions from this class to be sure that all views can update their tags. When calling data-manipulation functions, this class
|
||||
* will send beginTagChange and endTagChange signals with the correspond values. This class also keep the undo-stack of the changes.
|
||||
*
|
||||
* When document has changed, the signal documentChanged(bool) will be emitted.
|
||||
*/
|
||||
class ScxmlDocument : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The TagChange enum
|
||||
*/
|
||||
enum TagChange {
|
||||
TagAddChild = 0,
|
||||
TagAddTags,
|
||||
TagRemoveChild,
|
||||
TagRemoveTags,
|
||||
TagCurrentChanged,
|
||||
TagAttributesChanged,
|
||||
TagEditorInfoChanged,
|
||||
TagChangeParent,
|
||||
TagChangeParentRemoveChild,
|
||||
TagChangeParentAddChild,
|
||||
TagChangeOrder,
|
||||
TagContentChanged,
|
||||
TagChangeFullNameSpace
|
||||
};
|
||||
|
||||
explicit ScxmlDocument(const QString &fileName = QString(), QObject *parent = nullptr);
|
||||
explicit ScxmlDocument(const QByteArray &data, QObject *parent = nullptr);
|
||||
~ScxmlDocument() override;
|
||||
|
||||
void addNamespace(ScxmlNamespace *ns);
|
||||
ScxmlNamespace *scxmlNamespace(const QString &prefix);
|
||||
|
||||
/**
|
||||
* @brief setCurrentTag - inform views that current selected tag has changed
|
||||
* @param tag - current tag
|
||||
*/
|
||||
void setCurrentTag(ScxmlTag *tag);
|
||||
ScxmlTag *currentTag() const;
|
||||
|
||||
/**
|
||||
* @brief setContent - inform views that tag-content has changed
|
||||
* @param tag
|
||||
* @param content
|
||||
*/
|
||||
void setContent(ScxmlTag *tag, const QString &content);
|
||||
|
||||
/**
|
||||
* @brief setValue - inform views that tag-value has changed
|
||||
* @param tag
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
void setValue(ScxmlTag *tag, const QString &key, const QString &value);
|
||||
|
||||
/**
|
||||
* @brief setValue - inform views that tag-value has changed
|
||||
* @param tag
|
||||
* @param attributeIndex
|
||||
* @param value
|
||||
*/
|
||||
void setValue(ScxmlTag *tag, int attributeIndex, const QString &value);
|
||||
|
||||
/**
|
||||
* @brief setEditorInfo - inform views (and save undo-command) that editorinfo has changed
|
||||
* @param tag
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
void setEditorInfo(ScxmlTag *tag, const QString &key, const QString &value);
|
||||
|
||||
/**
|
||||
* @brief addTag - inform views that new child will be added to the tree
|
||||
* @param parent
|
||||
* @param child
|
||||
*/
|
||||
void addTag(ScxmlTag *parent, ScxmlTag *child);
|
||||
void addTags(ScxmlTag *parent, const QVector<ScxmlTag*> tags);
|
||||
|
||||
/**
|
||||
* @brief removeTag - inform views that tag will be removed
|
||||
* @param tag
|
||||
*/
|
||||
void removeTag(ScxmlTag *tag);
|
||||
|
||||
/**
|
||||
* @brief changeParent - inform views that tag parent will be changed
|
||||
* @param child
|
||||
* @param newParent
|
||||
* @param tagIndex
|
||||
*/
|
||||
void changeParent(ScxmlTag *child, ScxmlTag *newParent, int tagIndex = -1);
|
||||
|
||||
/**
|
||||
* @brief changeOrder - inform vies that tag's child-position will be changed
|
||||
* @param child
|
||||
* @param newPos
|
||||
*/
|
||||
void changeOrder(ScxmlTag *child, int newPos);
|
||||
|
||||
/**
|
||||
* @brief changed - holds the changes-status of the document
|
||||
* @return - true if changed, false otherwise
|
||||
*/
|
||||
bool changed() const;
|
||||
|
||||
/**
|
||||
* @brief rootTag - return rootTag of the document
|
||||
* @return
|
||||
*/
|
||||
ScxmlTag *rootTag() const;
|
||||
ScxmlTag *scxmlRootTag() const;
|
||||
void pushRootTag(ScxmlTag *tag);
|
||||
ScxmlTag *popRootTag();
|
||||
|
||||
/**
|
||||
* @brief fileName - return current filename of the document
|
||||
* @return
|
||||
*/
|
||||
QString fileName() const;
|
||||
void setFileName(const QString &filename);
|
||||
|
||||
/**
|
||||
* @brief undoStack - return undo-stack of the document (see UndoStack)
|
||||
* @return
|
||||
*/
|
||||
QUndoStack *undoStack() const;
|
||||
|
||||
/**
|
||||
* @brief save - save document with given filename
|
||||
* @param fileName -
|
||||
* @return return true if file has successfully wrote
|
||||
*/
|
||||
bool save(const QString &fileName);
|
||||
bool save();
|
||||
void load(const QString &fileName);
|
||||
bool pasteData(const QByteArray &data, const QPointF &minPos = QPointF(0, 0), const QPointF &pastePos = QPointF(0, 0));
|
||||
bool load(QIODevice *io);
|
||||
|
||||
/**
|
||||
* @brief nextId - generate and return next id depends on the given key
|
||||
* @param key
|
||||
* @return return value will be the form key_nextId
|
||||
*/
|
||||
QString nextUniqueId(const QString &key);
|
||||
QString getUniqueCopyId(const ScxmlTag *tag);
|
||||
|
||||
/**
|
||||
* @brief hasLayouted - tells is there qt-namespace available in the current loaded document
|
||||
* @return true or false
|
||||
*/
|
||||
bool hasLayouted() const;
|
||||
|
||||
void setLevelColors(const QVector<QColor> &colors);
|
||||
QColor getColor(int depth) const;
|
||||
|
||||
bool hasError() const
|
||||
{
|
||||
return m_hasError;
|
||||
}
|
||||
|
||||
QString lastError() const
|
||||
{
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
QByteArray content(const QVector<ScxmlTag*> &tags) const;
|
||||
QByteArray content(ScxmlTag *tag = nullptr) const;
|
||||
void clear(bool createRoot = true);
|
||||
|
||||
// Full NameSpace functions
|
||||
QString nameSpaceDelimiter() const;
|
||||
bool useFullNameSpace() const;
|
||||
void setNameSpaceDelimiter(const QString &delimiter);
|
||||
void setUseFullNameSpace(bool use);
|
||||
|
||||
void setUndoRedoRunning(bool para);
|
||||
|
||||
QFileInfo qtBinDir() const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief documentChanged - this signal will be emitted just after document has changed and is not in clean state
|
||||
* @param changed
|
||||
*/
|
||||
void documentChanged(bool changed);
|
||||
|
||||
/**
|
||||
* @brief beginTagChange - this signal will be emitted just before some tagchange will be made (see TagChange)
|
||||
* @param change
|
||||
* @param tag
|
||||
* @param value
|
||||
*/
|
||||
void beginTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag, const QVariant &value);
|
||||
|
||||
/**
|
||||
* @brief beginTagChange - this signal will be emitted just after some tagchange has made (see TagChange)
|
||||
* @param change
|
||||
* @param tag
|
||||
* @param value
|
||||
*/
|
||||
void endTagChange(ScxmlDocument::TagChange change, ScxmlTag *tag, const QVariant &value);
|
||||
|
||||
/**
|
||||
* @brief colorThemeChanged - this signal will be emitted just after color theme has changed
|
||||
*/
|
||||
void colorThemeChanged();
|
||||
|
||||
private:
|
||||
friend class ScxmlTag;
|
||||
friend class ChangeFullNameSpaceCommand;
|
||||
|
||||
void initErrorMessage(const QXmlStreamReader &xml, QIODevice *io);
|
||||
bool generateSCXML(QIODevice *io, ScxmlTag *tag = nullptr) const;
|
||||
void addChild(ScxmlTag *tag);
|
||||
void removeChild(ScxmlTag *tag);
|
||||
void printSCXML();
|
||||
void deleteRootTags();
|
||||
void clearNamespaces();
|
||||
void initVariables();
|
||||
void addTagRecursive(ScxmlTag *parent, ScxmlTag *tag);
|
||||
void removeTagRecursive(ScxmlTag *tag);
|
||||
|
||||
ScxmlTag *createScxmlTag();
|
||||
QString m_fileName;
|
||||
QUndoStack *m_undoStack;
|
||||
QVector<ScxmlTag*> m_tags;
|
||||
QHash<QString, int> m_nextIdHash;
|
||||
QHash<QString, QString> m_idMap;
|
||||
bool m_hasError = false;
|
||||
QString m_lastError;
|
||||
QVector<ScxmlTag*> m_rootTags;
|
||||
QMap<QString, ScxmlNamespace*> m_namespaces;
|
||||
QVector<QColor> m_colors;
|
||||
bool m_hasLayouted = false;
|
||||
QString m_idDelimiter;
|
||||
bool m_useFullNameSpace = false;
|
||||
ScxmlTag *m_currentTag = nullptr;
|
||||
bool m_undoRedoRunning = false;
|
||||
QFileInfo m_qtBinDir;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
55
src/plugins/scxmleditor/plugin_interface/scxmlnamespace.cpp
Normal file
55
src/plugins/scxmleditor/plugin_interface/scxmlnamespace.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scxmlnamespace.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ScxmlNamespace::ScxmlNamespace(const QString &prefix, const QString &name, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_prefix(prefix)
|
||||
, m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
QString ScxmlNamespace::prefix() const
|
||||
{
|
||||
return m_prefix;
|
||||
}
|
||||
|
||||
QString ScxmlNamespace::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
bool ScxmlNamespace::isTagVisible(const QString &tag) const
|
||||
{
|
||||
return m_tagVisibility.value(tag, true);
|
||||
}
|
||||
|
||||
void ScxmlNamespace::setTagVisibility(const QString &tag, bool visible)
|
||||
{
|
||||
m_tagVisibility[tag] = visible;
|
||||
}
|
||||
52
src/plugins/scxmleditor/plugin_interface/scxmlnamespace.h
Normal file
52
src/plugins/scxmleditor/plugin_interface/scxmlnamespace.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlNamespace : public QObject
|
||||
{
|
||||
public:
|
||||
ScxmlNamespace(const QString &prefix, const QString &name, QObject *parent = nullptr);
|
||||
|
||||
QString prefix() const;
|
||||
QString name() const;
|
||||
|
||||
bool isTagVisible(const QString &tag) const;
|
||||
void setTagVisibility(const QString &tag, bool visible);
|
||||
|
||||
private:
|
||||
QString m_prefix, m_name;
|
||||
QMap<QString, bool> m_tagVisibility;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
679
src/plugins/scxmleditor/plugin_interface/scxmltag.cpp
Normal file
679
src/plugins/scxmleditor/plugin_interface/scxmltag.cpp
Normal file
@@ -0,0 +1,679 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scxmltag.h"
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "scxmltagutils.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ScxmlTag::ScxmlTag(TagType type, ScxmlDocument *document)
|
||||
: m_prefix(
|
||||
QLatin1String(type == Metadata || type == MetadataItem ? "qt" : ""))
|
||||
{
|
||||
setDocument(document);
|
||||
init(type);
|
||||
m_tagName = QLatin1String(m_info->name);
|
||||
}
|
||||
|
||||
ScxmlTag::ScxmlTag(const QString &prefix, const QString &name,
|
||||
ScxmlDocument *document)
|
||||
: m_tagName(name)
|
||||
, m_prefix(prefix)
|
||||
{
|
||||
setDocument(document);
|
||||
TagType type = UnknownTag;
|
||||
for (int i = 0; i < Finalize; ++i) {
|
||||
if (QLatin1String(scxml_tags[i].name) == name) {
|
||||
type = (TagType)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
init(type);
|
||||
}
|
||||
|
||||
ScxmlTag::ScxmlTag(const ScxmlTag *other, bool copyChildren)
|
||||
{
|
||||
setDocument(other->m_document);
|
||||
m_tagType = other->m_tagType;
|
||||
m_tagName = other->m_tagName;
|
||||
m_content = other->m_content;
|
||||
m_prefix = other->m_prefix;
|
||||
m_info = &scxml_tags[m_tagType];
|
||||
m_attributeNames = other->m_attributeNames;
|
||||
m_attributeValues = other->m_attributeValues;
|
||||
m_editorInfo = other->m_editorInfo;
|
||||
|
||||
if (copyChildren) {
|
||||
for (int i = 0; i < other->m_childTags.count(); ++i)
|
||||
appendChild(new ScxmlTag(other->m_childTags[i], copyChildren));
|
||||
}
|
||||
}
|
||||
|
||||
ScxmlTag::~ScxmlTag()
|
||||
{
|
||||
if (m_document)
|
||||
m_document->removeChild(this);
|
||||
|
||||
m_attributeNames.clear();
|
||||
m_attributeValues.clear();
|
||||
m_childTags.clear();
|
||||
|
||||
// m_parentTag = 0;
|
||||
m_document = nullptr;
|
||||
m_info = nullptr;
|
||||
m_tagType = UnknownTag;
|
||||
}
|
||||
|
||||
void ScxmlTag::finalizeTagNames()
|
||||
{
|
||||
switch (m_tagType) {
|
||||
case State: {
|
||||
if (hasAttribute("initial")) {
|
||||
QString oldInitial = attribute("initial");
|
||||
QString newInitial = m_document->m_idMap.value(oldInitial);
|
||||
setAttribute("initial", newInitial);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = m_childTags.count(); i--;) {
|
||||
ScxmlTag *t = m_childTags[i];
|
||||
switch (t->tagType()) {
|
||||
case InitialTransition:
|
||||
case Transition: {
|
||||
QString oldTarget = t->attribute("target");
|
||||
QString newTarget = m_document->m_idMap.value(oldTarget);
|
||||
if (!oldTarget.isEmpty() && newTarget.isEmpty())
|
||||
delete m_childTags.takeAt(i);
|
||||
else
|
||||
t->setAttribute("target", newTarget);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
t->finalizeTagNames();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlTag::print()
|
||||
{
|
||||
qDebug() << "type " << m_tagType;
|
||||
qDebug() << "name " << m_tagName;
|
||||
qDebug() << "parent " << (m_parentTag ? m_parentTag->m_tagName : "");
|
||||
qDebug() << "attributeNames " << m_attributeNames;
|
||||
qDebug() << "attributeValues " << m_attributeValues;
|
||||
qDebug() << "childcount " << m_childTags.count();
|
||||
for (int i = 0; i < m_childTags.count(); ++i)
|
||||
qDebug() << " child " << i << m_childTags[i]->m_tagName;
|
||||
}
|
||||
|
||||
void ScxmlTag::init(TagType type)
|
||||
{
|
||||
m_tagType = type;
|
||||
m_info = &scxml_tags[type];
|
||||
|
||||
for (int i = 0; i < m_info->n_attributes; ++i) {
|
||||
if (m_info->attributes[i].value)
|
||||
setAttribute(
|
||||
QLatin1String(m_info->attributes[i].name),
|
||||
QString::fromLatin1(m_info->attributes[i].value).split(";").first());
|
||||
}
|
||||
|
||||
initId();
|
||||
}
|
||||
|
||||
void ScxmlTag::initId()
|
||||
{
|
||||
// Init state IDs
|
||||
if (m_document) {
|
||||
switch (m_tagType) {
|
||||
case State:
|
||||
setAttribute("id", m_document->nextUniqueId("State"));
|
||||
break;
|
||||
case Parallel:
|
||||
setAttribute("id", m_document->nextUniqueId("Parallel"));
|
||||
break;
|
||||
case History:
|
||||
setAttribute("id", m_document->nextUniqueId("History"));
|
||||
break;
|
||||
case Transition:
|
||||
setAttribute("event", m_document->nextUniqueId("Transition"));
|
||||
break;
|
||||
case Final:
|
||||
setAttribute("id", m_document->nextUniqueId("Final"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlTag::setDocument(ScxmlDocument *document)
|
||||
{
|
||||
if (m_document != document) {
|
||||
if (m_document)
|
||||
m_document->removeChild(this);
|
||||
|
||||
m_document = document;
|
||||
if (m_document)
|
||||
m_document->addChild(this);
|
||||
}
|
||||
}
|
||||
|
||||
ScxmlDocument *ScxmlTag::document() const
|
||||
{
|
||||
return m_document;
|
||||
}
|
||||
|
||||
const scxmltag_type_t *ScxmlTag::info() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
TagType ScxmlTag::tagType() const
|
||||
{
|
||||
return m_tagType;
|
||||
}
|
||||
|
||||
QString ScxmlTag::prefix() const
|
||||
{
|
||||
return m_prefix;
|
||||
}
|
||||
|
||||
void ScxmlTag::setTagName(const QString &name)
|
||||
{
|
||||
m_tagName = name;
|
||||
}
|
||||
|
||||
QString ScxmlTag::tagName(bool addPrefix) const
|
||||
{
|
||||
if (m_prefix.isEmpty() || !addPrefix)
|
||||
return m_tagName;
|
||||
else
|
||||
return QString::fromLatin1("%1:%2").arg(m_prefix).arg(m_tagName);
|
||||
}
|
||||
|
||||
QString ScxmlTag::displayName() const
|
||||
{
|
||||
switch (m_tagType) {
|
||||
case State:
|
||||
case Parallel:
|
||||
case Final:
|
||||
return attribute("id");
|
||||
case Transition:
|
||||
case InitialTransition:
|
||||
return attribute("event");
|
||||
break;
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
QString ScxmlTag::stateNameSpace() const
|
||||
{
|
||||
if (m_parentTag) {
|
||||
switch (m_parentTag->m_tagType) {
|
||||
case State:
|
||||
case Parallel:
|
||||
return QString::fromLatin1("%1%2%3")
|
||||
.arg(m_parentTag->stateNameSpace())
|
||||
.arg(m_parentTag->attribute(
|
||||
m_parentTag->m_attributeNames.indexOf("id")))
|
||||
.arg(m_document->nameSpaceDelimiter());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString ScxmlTag::content() const
|
||||
{
|
||||
return m_content;
|
||||
}
|
||||
|
||||
void ScxmlTag::setContent(const QString &content)
|
||||
{
|
||||
m_content = content.trimmed();
|
||||
}
|
||||
|
||||
bool ScxmlTag::hasData() const
|
||||
{
|
||||
if (m_attributeNames.count() > 0 || !m_content.isEmpty())
|
||||
return true;
|
||||
|
||||
foreach (ScxmlTag *tag, m_childTags) {
|
||||
if (tag->hasData())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScxmlTag::hasChild(TagType type) const
|
||||
{
|
||||
foreach (ScxmlTag *tag, m_childTags) {
|
||||
if (tag->tagType() == type)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScxmlTag::hasChild(const QString &name) const
|
||||
{
|
||||
foreach (ScxmlTag *tag, m_childTags) {
|
||||
if (tag->tagName() == name)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScxmlTag::insertChild(int index, ScxmlTag *child)
|
||||
{
|
||||
if (index >= 0 && index < m_childTags.count()) {
|
||||
m_childTags.insert(index, child);
|
||||
child->setParentTag(this);
|
||||
} else
|
||||
appendChild(child);
|
||||
}
|
||||
|
||||
void ScxmlTag::appendChild(ScxmlTag *child)
|
||||
{
|
||||
if (!m_childTags.contains(child)) {
|
||||
m_childTags.append(child);
|
||||
child->setParentTag(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlTag::removeChild(ScxmlTag *child)
|
||||
{
|
||||
m_childTags.removeAll(child);
|
||||
}
|
||||
|
||||
void ScxmlTag::moveChild(int oldPos, int newPos)
|
||||
{
|
||||
m_childTags.insert(newPos, m_childTags.takeAt(oldPos));
|
||||
}
|
||||
|
||||
QString ScxmlTag::attributeName(int ind) const
|
||||
{
|
||||
if (ind >= 0 && ind < m_attributeNames.count())
|
||||
return m_attributeNames[ind];
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString ScxmlTag::attribute(int ind, const QString &defaultValue) const
|
||||
{
|
||||
if (ind >= 0 && ind < m_attributeValues.count())
|
||||
return m_attributeValues[ind];
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void ScxmlTag::setEditorInfo(const QString &key, const QString &value)
|
||||
{
|
||||
if (value.isEmpty())
|
||||
m_editorInfo.remove(key);
|
||||
else
|
||||
m_editorInfo[key] = value;
|
||||
}
|
||||
|
||||
QString ScxmlTag::editorInfo(const QString &key) const
|
||||
{
|
||||
return m_editorInfo.value(key);
|
||||
}
|
||||
|
||||
bool ScxmlTag::hasEditorInfo(const QString &key) const
|
||||
{
|
||||
return m_editorInfo.keys().contains(key);
|
||||
}
|
||||
|
||||
void ScxmlTag::setAttributeName(int ind, const QString &name)
|
||||
{
|
||||
if (m_attributeNames.contains(name))
|
||||
return;
|
||||
|
||||
if (ind >= 0 && ind < m_attributeValues.count()) {
|
||||
m_attributeNames[ind] = name;
|
||||
} else {
|
||||
m_attributeNames << name;
|
||||
m_attributeValues << QCoreApplication::translate(
|
||||
"SXCMLTag::UnknownAttributeValue", "Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlTag::setAttribute(int ind, const QString &value)
|
||||
{
|
||||
if (ind >= 0 && ind < m_attributeNames.count())
|
||||
setAttribute(m_attributeNames[ind], value);
|
||||
else {
|
||||
m_attributeNames << QCoreApplication::translate(
|
||||
"SXCMLTag::UnknownAttributeName", "Unknown");
|
||||
m_attributeValues << value;
|
||||
}
|
||||
}
|
||||
|
||||
void ScxmlTag::setAttribute(const QString &name, const QString &value)
|
||||
{
|
||||
if (value.isEmpty()) {
|
||||
int ind = m_attributeNames.indexOf(name);
|
||||
if (ind >= 0 && ind < m_attributeNames.count()) {
|
||||
m_attributeNames.removeAt(ind);
|
||||
m_attributeValues.removeAt(ind);
|
||||
}
|
||||
} else if (name.isEmpty()) {
|
||||
int ind = m_attributeValues.indexOf(value);
|
||||
if (ind >= 0 && ind < m_attributeValues.count()) {
|
||||
m_attributeNames.removeAt(ind);
|
||||
m_attributeValues.removeAt(ind);
|
||||
}
|
||||
} else {
|
||||
int ind = m_attributeNames.indexOf(name);
|
||||
if (ind >= 0 && ind < m_attributeNames.count()) {
|
||||
m_attributeNames[ind] = name;
|
||||
m_attributeValues[ind] = value;
|
||||
} else {
|
||||
m_attributeNames << name;
|
||||
m_attributeValues << value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList ScxmlTag::attributeNames() const
|
||||
{
|
||||
return m_attributeNames;
|
||||
}
|
||||
|
||||
QStringList ScxmlTag::attributeValues() const
|
||||
{
|
||||
return m_attributeValues;
|
||||
}
|
||||
|
||||
int ScxmlTag::attributeCount() const
|
||||
{
|
||||
return m_attributeNames.count();
|
||||
}
|
||||
|
||||
QString ScxmlTag::attribute(const QString &attr, bool useNameSpace,
|
||||
const QString &defaultValue) const
|
||||
{
|
||||
QString value = attribute(m_attributeNames.indexOf(attr), defaultValue);
|
||||
if (useNameSpace && m_document->useFullNameSpace())
|
||||
return QString::fromLatin1("%1%2").arg(stateNameSpace()).arg(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ScxmlTag::hasAttribute(const QString &key) const
|
||||
{
|
||||
return m_attributeNames.contains(key);
|
||||
}
|
||||
|
||||
int ScxmlTag::childCount() const
|
||||
{
|
||||
return m_childTags.count();
|
||||
}
|
||||
|
||||
int ScxmlTag::childIndex(const ScxmlTag *child) const
|
||||
{
|
||||
return m_childTags.indexOf(const_cast<ScxmlTag*>(child));
|
||||
}
|
||||
|
||||
void ScxmlTag::setParentTag(ScxmlTag *parentTag)
|
||||
{
|
||||
m_parentTag = parentTag;
|
||||
}
|
||||
|
||||
bool ScxmlTag::hasParentTag() const
|
||||
{
|
||||
return m_parentTag != nullptr;
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlTag::child(int index) const
|
||||
{
|
||||
return index >= 0 && index < m_childTags.count()
|
||||
? m_childTags.value(index)
|
||||
: 0;
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlTag::parentTag() const
|
||||
{
|
||||
return m_parentTag;
|
||||
}
|
||||
|
||||
int ScxmlTag::index() const
|
||||
{
|
||||
return m_parentTag ? m_parentTag->childIndex(const_cast<ScxmlTag*>(this))
|
||||
: 0;
|
||||
}
|
||||
|
||||
bool ScxmlTag::isRootTag() const
|
||||
{
|
||||
return m_document->rootTag() == this;
|
||||
}
|
||||
|
||||
QVector<ScxmlTag*> ScxmlTag::allChildren() const
|
||||
{
|
||||
return m_childTags;
|
||||
}
|
||||
|
||||
QVector<ScxmlTag*> ScxmlTag::children(const QString &name) const
|
||||
{
|
||||
QVector<ScxmlTag*> children;
|
||||
foreach (ScxmlTag *tag, m_childTags) {
|
||||
if (tag->tagName() == name)
|
||||
children << tag;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
ScxmlTag *ScxmlTag::child(const QString &name) const
|
||||
{
|
||||
foreach (ScxmlTag *tag, m_childTags) {
|
||||
if (tag->tagName() == name)
|
||||
return tag;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ScxmlTag::writeXml(QXmlStreamWriter &xml)
|
||||
{
|
||||
// Start tag
|
||||
xml.writeStartElement(tagName());
|
||||
|
||||
// Don't write attribute if type is Script and content is available
|
||||
if (m_tagType != Script || m_content.isEmpty()) {
|
||||
for (int i = 0; i < m_attributeNames.count(); ++i) {
|
||||
if (m_attributeNames[i] == "id" && m_document->useFullNameSpace())
|
||||
xml.writeAttribute("id", attribute("id", true));
|
||||
else
|
||||
xml.writeAttribute(m_attributeNames[i], m_attributeValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// If tag is Scxml (root), we need to fine-tune initial-state
|
||||
if (m_tagType == Scxml) {
|
||||
setEditorInfo("initialGeometry", QString());
|
||||
setEditorInfo("transitionGeometry", QString());
|
||||
|
||||
ScxmlTag *initialTag = child("initial");
|
||||
if (initialTag) {
|
||||
setEditorInfo("initialGeometry", initialTag->editorInfo(Constants::C_SCXML_EDITORINFO_GEOMETRY));
|
||||
|
||||
ScxmlTag *initialTransitionTag = initialTag->child("transition");
|
||||
if (initialTransitionTag) {
|
||||
xml.writeAttribute("initial",
|
||||
initialTransitionTag->attribute("target"));
|
||||
setEditorInfo("transitionGeometry",
|
||||
initialTransitionTag->editorInfo(Constants::C_SCXML_EDITORINFO_GEOMETRY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write content if necessary
|
||||
if (m_info->canIncludeContent && !m_content.isEmpty())
|
||||
xml.writeCharacters(m_content);
|
||||
|
||||
// Write editorinfo if necessary
|
||||
if (!m_editorInfo.isEmpty()) {
|
||||
xml.writeStartElement("qt:editorinfo");
|
||||
QHashIterator<QString, QString> i(m_editorInfo);
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
xml.writeAttribute(i.key(), i.value());
|
||||
}
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
// Write children states
|
||||
for (int i = 0; i < m_childTags.count(); ++i) {
|
||||
if (m_tagType == Scxml && m_childTags[i]->tagType() == Initial)
|
||||
continue;
|
||||
|
||||
if ((m_childTags[i]->tagType() == Metadata || m_childTags[i]->tagType() == MetadataItem) && !m_childTags[i]->hasData())
|
||||
continue;
|
||||
|
||||
m_childTags[i]->writeXml(xml);
|
||||
}
|
||||
|
||||
// End tag
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
void ScxmlTag::readXml(QXmlStreamReader &xml, bool checkCopyId)
|
||||
{
|
||||
QString scxmlInitial;
|
||||
|
||||
// Read and set attributes
|
||||
QXmlStreamAttributes attributes = xml.attributes();
|
||||
for (int i = 0; i < attributes.count(); ++i) {
|
||||
if (m_tagType == Scxml && attributes[i].qualifiedName() == "initial")
|
||||
scxmlInitial = attributes[i].value().toString();
|
||||
else {
|
||||
QString key = attributes[i].qualifiedName().toString();
|
||||
QString value = attributes[i].value().toString();
|
||||
|
||||
// Modify id-attribute if necessary
|
||||
switch (m_tagType) {
|
||||
case History:
|
||||
case Final:
|
||||
case State:
|
||||
case Parallel:
|
||||
case Initial: {
|
||||
if (key == "id") {
|
||||
setAttribute(key, value);
|
||||
|
||||
QString oldId = value;
|
||||
QString parentNS = stateNameSpace();
|
||||
if (value.startsWith(parentNS))
|
||||
value.remove(parentNS);
|
||||
|
||||
if (checkCopyId)
|
||||
value = m_document->getUniqueCopyId(this);
|
||||
if (m_document->useFullNameSpace())
|
||||
m_document->m_idMap[oldId] = QString::fromLatin1("%1%2").arg(stateNameSpace()).arg(value);
|
||||
else
|
||||
m_document->m_idMap[oldId] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setAttribute(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Read children states
|
||||
QXmlStreamReader::TokenType token = xml.readNext();
|
||||
while (token != QXmlStreamReader::EndElement) {
|
||||
if (token == QXmlStreamReader::Characters)
|
||||
m_content = xml.text().toString().trimmed();
|
||||
else if (token == QXmlStreamReader::StartElement) {
|
||||
if (m_tagType != Metadata && m_tagType != MetadataItem && xml.qualifiedName().toString() == "qt:editorinfo") {
|
||||
// Read editorinfos
|
||||
QXmlStreamAttributes attributes = xml.attributes();
|
||||
foreach (QXmlStreamAttribute attr, attributes) {
|
||||
m_editorInfo[attr.name().toString()] = attr.value().toString();
|
||||
}
|
||||
|
||||
// Update fullnamespace-type of the scxmldocument
|
||||
if (m_tagType == Scxml) {
|
||||
m_document->m_useFullNameSpace = m_editorInfo.value("fullnamespace", "false") == "true";
|
||||
m_document->m_idDelimiter = m_editorInfo.value("fullnamespacedelimiter", "::");
|
||||
}
|
||||
|
||||
xml.readNext();
|
||||
} else {
|
||||
ScxmlTag *childTag = nullptr;
|
||||
if ((m_tagType == Initial || m_tagType == History) && xml.name().toString() == "transition")
|
||||
childTag = new ScxmlTag(InitialTransition, m_document);
|
||||
else
|
||||
childTag = new ScxmlTag(xml.prefix().toString(),
|
||||
xml.name().toString(), m_document);
|
||||
|
||||
appendChild(childTag);
|
||||
childTag->readXml(xml, checkCopyId);
|
||||
}
|
||||
} else if (token == QXmlStreamReader::Invalid) {
|
||||
qDebug() << ScxmlTag::tr("Error in reading XML ") << xml.error() << ":"
|
||||
<< xml.errorString();
|
||||
break;
|
||||
}
|
||||
|
||||
token = xml.readNext();
|
||||
}
|
||||
|
||||
// Create initial state of the scxml (root)
|
||||
if (m_tagType == Scxml && !scxmlInitial.isEmpty()) {
|
||||
auto initialTag = new ScxmlTag(Initial, m_document);
|
||||
auto initialTransitionTag = new ScxmlTag(InitialTransition, m_document);
|
||||
initialTransitionTag->setAttribute("target", scxmlInitial);
|
||||
initialTag->setEditorInfo(Constants::C_SCXML_EDITORINFO_GEOMETRY,
|
||||
m_editorInfo.value("initialGeometry"));
|
||||
initialTransitionTag->setEditorInfo(
|
||||
Constants::C_SCXML_EDITORINFO_GEOMETRY, m_editorInfo.value("transitionGeometry"));
|
||||
|
||||
appendChild(initialTag);
|
||||
initialTag->appendChild(initialTransitionTag);
|
||||
}
|
||||
}
|
||||
148
src/plugins/scxmleditor/plugin_interface/scxmltag.h
Normal file
148
src/plugins/scxmleditor/plugin_interface/scxmltag.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scxmltypes.h"
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QStringList>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlDocument;
|
||||
|
||||
/**
|
||||
* @brief The ScxmlTag class represents one element in the SCXML document tree.
|
||||
*
|
||||
* Tag have a tagType, info and zero or more attributes associated with them. TagType must be given in the constructor and
|
||||
* it is not possible to change it. You can get and set attributes with the functions attribute(), setAttribute() and hasAttribute().
|
||||
*
|
||||
* ScxmlTag has one parent-tag and zero or more child. Tag doesn't take ownerships of the children.
|
||||
* It is user responsibility to delete all tags. Normally this will be done via the ScxmlDocument inside the undo-commands.
|
||||
*/
|
||||
class ScxmlTag : public QObject
|
||||
{
|
||||
public:
|
||||
ScxmlTag(TagType type, ScxmlDocument *document = nullptr);
|
||||
ScxmlTag(const QString &prefix, const QString &name, ScxmlDocument *document = nullptr);
|
||||
ScxmlTag(const ScxmlTag *other, bool copyChildren = true);
|
||||
|
||||
~ScxmlTag() override;
|
||||
|
||||
void setDocument(ScxmlDocument *document);
|
||||
ScxmlDocument *document() const;
|
||||
|
||||
// Functions for handling tagType/tagName
|
||||
TagType tagType() const;
|
||||
QString prefix() const;
|
||||
QString tagName(bool addPrefix = true) const;
|
||||
void setTagName(const QString &name);
|
||||
const scxmltag_type_t *info() const;
|
||||
QString displayName() const;
|
||||
QString stateNameSpace() const;
|
||||
|
||||
// Get/set content
|
||||
QString content() const;
|
||||
void setContent(const QString &content);
|
||||
|
||||
// Handling editorInfo
|
||||
void setEditorInfo(const QString &key, const QString &value);
|
||||
QString editorInfo(const QString &key) const;
|
||||
bool hasEditorInfo(const QString &key) const;
|
||||
|
||||
// Functions for handling attributes
|
||||
int attributeCount() const;
|
||||
QStringList attributeNames() const;
|
||||
QStringList attributeValues() const;
|
||||
void setAttributeName(int ind, const QString &name);
|
||||
void setAttribute(int ind, const QString &name);
|
||||
QString attributeName(int ind) const;
|
||||
QString attribute(const QString &attribute, bool useNameSpace = false, const QString &defaultValue = QString()) const;
|
||||
QString attribute(int ind, const QString &defaultValue = QString()) const;
|
||||
void setAttribute(const QString &attribute, const QString &value);
|
||||
bool hasAttribute(const QString &key) const;
|
||||
|
||||
// Functions for handling parent
|
||||
void setParentTag(ScxmlTag *parentTag);
|
||||
ScxmlTag *parentTag() const;
|
||||
bool hasParentTag() const;
|
||||
|
||||
// Functions for handling child tags
|
||||
bool hasData() const;
|
||||
bool hasChild(TagType type) const;
|
||||
bool hasChild(const QString &name) const;
|
||||
void insertChild(int index, ScxmlTag *child);
|
||||
void appendChild(ScxmlTag *child);
|
||||
void removeChild(ScxmlTag *child);
|
||||
void moveChild(int oldPos, int newPos);
|
||||
int childCount() const;
|
||||
QVector<ScxmlTag*> allChildren() const;
|
||||
QVector<ScxmlTag*> children(const QString &name) const;
|
||||
ScxmlTag *child(const QString &name) const;
|
||||
ScxmlTag *child(int row) const;
|
||||
int childIndex(const ScxmlTag *child) const;
|
||||
int index() const;
|
||||
bool isRootTag() const;
|
||||
|
||||
/**
|
||||
* @brief writeXml - write tag's content with the QXMLStreamWriter. Call writeXml-function for all children too.
|
||||
* @param xml
|
||||
*/
|
||||
void writeXml(QXmlStreamWriter &xml);
|
||||
|
||||
/**
|
||||
* @brief readXml - read tag's information from the QXMLStreamReader and create child tags if necessary.
|
||||
* @param xml
|
||||
*/
|
||||
void readXml(QXmlStreamReader &xml, bool checkCopyId = false);
|
||||
|
||||
void finalizeTagNames();
|
||||
void print();
|
||||
|
||||
private:
|
||||
void init(TagType type);
|
||||
void initId();
|
||||
|
||||
const scxmltag_type_t *m_info = nullptr;
|
||||
QStringList m_attributeNames;
|
||||
QStringList m_attributeValues;
|
||||
QPointer<ScxmlTag> m_parentTag;
|
||||
QVector<ScxmlTag*> m_childTags;
|
||||
QPointer<ScxmlDocument> m_document;
|
||||
TagType m_tagType = UnknownTag;
|
||||
QString m_tagName;
|
||||
QString m_content;
|
||||
QString m_prefix;
|
||||
QHash<QString, QString> m_editorInfo;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
386
src/plugins/scxmleditor/plugin_interface/scxmltagutils.cpp
Normal file
386
src/plugins/scxmleditor/plugin_interface/scxmltagutils.cpp
Normal file
@@ -0,0 +1,386 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scxmltagutils.h"
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "serializer.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QPointF>
|
||||
#include <QRectF>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
namespace TagUtils {
|
||||
|
||||
bool checkPaste(const QString &copiedTagTypes, const ScxmlTag *currentTag)
|
||||
{
|
||||
if (copiedTagTypes.isEmpty() || currentTag == nullptr)
|
||||
return false;
|
||||
|
||||
QVector<TagType> tagTypes;
|
||||
for (int i = 0; i < Finalize; ++i) {
|
||||
if (copiedTagTypes.contains(QLatin1String(scxml_tags[i].name)))
|
||||
tagTypes << TagType(i);
|
||||
}
|
||||
|
||||
tagTypes.removeAll(InitialTransition);
|
||||
|
||||
if (tagTypes.isEmpty())
|
||||
return false;
|
||||
|
||||
QVector<TagType> childTags = allowedChildTypes(currentTag->tagType());
|
||||
foreach (const TagType &type, tagTypes) {
|
||||
if (!childTags.contains(type))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void createChildMenu(const ScxmlTag *tag, QMenu *menu, bool addRemove)
|
||||
{
|
||||
QTC_ASSERT(tag, return);
|
||||
|
||||
initChildMenu(tag->tagType(), menu);
|
||||
|
||||
QVariantMap data;
|
||||
data[Constants::C_SCXMLTAG_PARENTTAG] = tag->tagType();
|
||||
data[Constants::C_SCXMLTAG_ACTIONTYPE] = AddChild;
|
||||
|
||||
if (tag->tagType() == UnknownTag) {
|
||||
data[Constants::C_SCXMLTAG_TAGTYPE] = UnknownTag;
|
||||
menu->addAction(ScxmlTag::tr("New Tag"))->setData(data);
|
||||
} else if (tag->tagType() == Metadata) {
|
||||
data[Constants::C_SCXMLTAG_TAGTYPE] = MetadataItem;
|
||||
menu->addAction(ScxmlTag::tr("Item"))->setData(data);
|
||||
} else {
|
||||
data[Constants::C_SCXMLTAG_PARENTTAG] = Metadata;
|
||||
data[Constants::C_SCXMLTAG_TAGTYPE] = MetadataItem;
|
||||
menu->addAction(ScxmlTag::tr("Metadata"))->setData(data);
|
||||
}
|
||||
|
||||
if (addRemove) {
|
||||
menu->addSeparator();
|
||||
data[Constants::C_SCXMLTAG_ACTIONTYPE] = Remove;
|
||||
QAction *act = menu->addAction(ScxmlTag::tr("Remove"));
|
||||
act->setData(data);
|
||||
act->setEnabled(!tag->isRootTag());
|
||||
}
|
||||
}
|
||||
|
||||
QVector<TagType> allowedChildTypes(TagType tagType)
|
||||
{
|
||||
QVector<TagType> childTags;
|
||||
|
||||
switch (tagType) {
|
||||
case Scxml:
|
||||
childTags << DataModel;
|
||||
childTags << Script;
|
||||
childTags << Initial;
|
||||
childTags << State;
|
||||
childTags << Parallel;
|
||||
childTags << Final;
|
||||
break;
|
||||
case State:
|
||||
childTags << Initial;
|
||||
childTags << Final;
|
||||
case Parallel:
|
||||
childTags << OnEntry;
|
||||
childTags << OnExit;
|
||||
childTags << Transition;
|
||||
childTags << DataModel;
|
||||
childTags << Invoke;
|
||||
childTags << State;
|
||||
childTags << Parallel;
|
||||
childTags << History;
|
||||
break;
|
||||
case Initial:
|
||||
case History:
|
||||
childTags << Transition;
|
||||
break;
|
||||
case Final:
|
||||
childTags << OnEntry;
|
||||
childTags << OnExit;
|
||||
childTags << Donedata;
|
||||
break;
|
||||
case If:
|
||||
childTags << ElseIf;
|
||||
childTags << Else;
|
||||
case Transition:
|
||||
case OnEntry:
|
||||
case OnExit:
|
||||
case ElseIf:
|
||||
case Else:
|
||||
case Foreach:
|
||||
// Executable content
|
||||
childTags << Raise;
|
||||
childTags << Send;
|
||||
childTags << Script;
|
||||
childTags << Assign;
|
||||
childTags << Cancel;
|
||||
childTags << Log;
|
||||
childTags << If;
|
||||
childTags << Foreach;
|
||||
break;
|
||||
case DataModel:
|
||||
childTags << Data;
|
||||
break;
|
||||
case Data:
|
||||
// PENDING
|
||||
break;
|
||||
case Assign:
|
||||
// PENDING
|
||||
break;
|
||||
case Content:
|
||||
// PENDING
|
||||
break;
|
||||
case Script:
|
||||
// PENDING
|
||||
break;
|
||||
case Invoke:
|
||||
childTags << Finalize;
|
||||
case Donedata:
|
||||
case Send:
|
||||
childTags << Param;
|
||||
childTags << Content;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return childTags;
|
||||
}
|
||||
|
||||
QVector<TagType> childTypes(TagType tagType)
|
||||
{
|
||||
QVector<TagType> childTags;
|
||||
|
||||
switch (tagType) {
|
||||
case Scxml:
|
||||
childTags << DataModel;
|
||||
childTags << Script;
|
||||
break;
|
||||
case State:
|
||||
case Parallel:
|
||||
childTags << OnEntry;
|
||||
childTags << OnExit;
|
||||
childTags << Transition;
|
||||
childTags << DataModel;
|
||||
childTags << Invoke;
|
||||
break;
|
||||
case Initial:
|
||||
case History:
|
||||
//childTags << Transition;
|
||||
break;
|
||||
case Final:
|
||||
childTags << OnEntry;
|
||||
childTags << OnExit;
|
||||
childTags << Donedata;
|
||||
break;
|
||||
case If:
|
||||
childTags << ElseIf;
|
||||
childTags << Else;
|
||||
case Transition:
|
||||
case OnEntry:
|
||||
case OnExit:
|
||||
case ElseIf:
|
||||
case Else:
|
||||
case Foreach:
|
||||
// Executable content
|
||||
childTags << Raise;
|
||||
childTags << Send;
|
||||
childTags << Script;
|
||||
childTags << Assign;
|
||||
childTags << Cancel;
|
||||
childTags << Log;
|
||||
childTags << If;
|
||||
childTags << Foreach;
|
||||
break;
|
||||
case DataModel:
|
||||
childTags << Data;
|
||||
break;
|
||||
case Data:
|
||||
// PENDING
|
||||
break;
|
||||
case Assign:
|
||||
// PENDING
|
||||
break;
|
||||
case Content:
|
||||
// PENDING
|
||||
break;
|
||||
case Script:
|
||||
// PENDING
|
||||
break;
|
||||
case Invoke:
|
||||
childTags << Finalize;
|
||||
case Donedata:
|
||||
case Send:
|
||||
childTags << Param;
|
||||
childTags << Content;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return childTags;
|
||||
}
|
||||
|
||||
void initChildMenu(TagType tagType, QMenu *menu)
|
||||
{
|
||||
menu->setTitle(QLatin1String(scxml_tags[tagType].name));
|
||||
|
||||
QVector<TagType> childTags = childTypes(tagType);
|
||||
|
||||
if (childTags.count() > 0) {
|
||||
for (int i = 0; i < childTags.count(); ++i) {
|
||||
if (childTags[i] == OnEntry || childTags[i] == OnExit)
|
||||
initChildMenu(childTags[i], menu->addMenu(QLatin1String(scxml_tags[childTags[i]].name)));
|
||||
else {
|
||||
QVariantMap data;
|
||||
data[Constants::C_SCXMLTAG_PARENTTAG] = tagType;
|
||||
data[Constants::C_SCXMLTAG_TAGTYPE] = childTags[i];
|
||||
data[Constants::C_SCXMLTAG_ACTIONTYPE] = AddChild;
|
||||
menu->addAction(QLatin1String(scxml_tags[childTags[i]].name))->setData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScxmlTag *metadataTag(ScxmlTag *tag, const QString &key, bool blockUpdates)
|
||||
{
|
||||
QTC_ASSERT(tag, return nullptr);
|
||||
|
||||
ScxmlTag *info = nullptr;
|
||||
|
||||
ScxmlDocument *document = tag->document();
|
||||
if (document) {
|
||||
ScxmlTag *metaData = tag->child("qt:metadata");
|
||||
if (!metaData) {
|
||||
metaData = new ScxmlTag(Metadata, document);
|
||||
if (!blockUpdates)
|
||||
document->addTag(tag, metaData);
|
||||
else
|
||||
tag->appendChild(metaData);
|
||||
}
|
||||
|
||||
info = metaData->child(QString::fromLatin1("qt:%1").arg(key));
|
||||
if (!info) {
|
||||
info = new ScxmlTag(Metadata, document);
|
||||
info->setTagName(key);
|
||||
if (!blockUpdates)
|
||||
document->addTag(metaData, info);
|
||||
else
|
||||
metaData->appendChild(info);
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
ScxmlTag *findChild(const ScxmlTag *tag, TagType childType)
|
||||
{
|
||||
QTC_ASSERT(tag, return nullptr);
|
||||
|
||||
for (int i = 0; i < tag->childCount(); ++i) {
|
||||
if (tag->child(i)->tagType() == childType)
|
||||
return tag->child(i);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void findAllChildren(const ScxmlTag *tag, QVector<ScxmlTag*> &children)
|
||||
{
|
||||
QTC_ASSERT(tag, return);
|
||||
|
||||
for (int i = 0; i < tag->childCount(); ++i) {
|
||||
ScxmlTag *child = tag->child(i);
|
||||
children << child;
|
||||
findAllChildren(child, children);
|
||||
}
|
||||
}
|
||||
|
||||
void findAllTransitionChildren(const ScxmlTag *tag, QVector<ScxmlTag*> &children)
|
||||
{
|
||||
QTC_ASSERT(tag, return);
|
||||
|
||||
for (int i = 0; i < tag->childCount(); ++i) {
|
||||
ScxmlTag *child = tag->child(i);
|
||||
TagType t = child->tagType();
|
||||
if (t == Transition || t == InitialTransition)
|
||||
children << child;
|
||||
else
|
||||
findAllTransitionChildren(child, children);
|
||||
}
|
||||
}
|
||||
|
||||
void modifyPosition(ScxmlTag *tag, const QPointF &minPos, const QPointF &targetPos)
|
||||
{
|
||||
QTC_ASSERT(tag, return);
|
||||
|
||||
const QString sceneData = tag->editorInfo(Constants::C_SCXML_EDITORINFO_SCENEGEOMETRY);
|
||||
const QString localData = tag->editorInfo(Constants::C_SCXML_EDITORINFO_GEOMETRY);
|
||||
|
||||
Serializer s;
|
||||
if (!localData.isEmpty() && !sceneData.isEmpty()) {
|
||||
QPointF localPos, scenePos;
|
||||
QRectF localRect, sceneRect;
|
||||
|
||||
s.setData(sceneData);
|
||||
s.read(scenePos);
|
||||
s.read(sceneRect);
|
||||
|
||||
s.clear();
|
||||
s.setData(localData);
|
||||
s.read(localPos);
|
||||
s.read(localRect);
|
||||
|
||||
localPos = targetPos - localRect.topLeft() - (minPos - sceneRect.topLeft());
|
||||
|
||||
s.clear();
|
||||
s.append(localPos);
|
||||
s.append(localRect);
|
||||
tag->document()->setEditorInfo(tag, Constants::C_SCXML_EDITORINFO_GEOMETRY, s.data());
|
||||
} else {
|
||||
s.append(targetPos);
|
||||
if (tag->tagType() == State || tag->tagType() == Parallel)
|
||||
s.append(QRectF(-60, -50, 120, 100));
|
||||
else if (tag->tagType() == Initial || tag->tagType() == Final || tag->tagType() == History)
|
||||
s.append(QRectF(-20, -20, 40, 40));
|
||||
else
|
||||
s.append(QRectF());
|
||||
tag->document()->setEditorInfo(tag, Constants::C_SCXML_EDITORINFO_GEOMETRY, s.data());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TagUtils
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
60
src/plugins/scxmleditor/plugin_interface/scxmltagutils.h
Normal file
60
src/plugins/scxmleditor/plugin_interface/scxmltagutils.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scxmltag.h"
|
||||
#include <QMenu>
|
||||
#include <QVector>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
namespace TagUtils {
|
||||
|
||||
enum MenuAction {
|
||||
AddChild = 0,
|
||||
SetAsInitial,
|
||||
Relayout,
|
||||
ZoomToState,
|
||||
RemovePoint,
|
||||
Remove
|
||||
};
|
||||
|
||||
bool checkPaste(const QString &copiedTagType, const ScxmlTag *currentTag);
|
||||
QVector<TagType> allowedChildTypes(TagType tagType);
|
||||
QVector<TagType> childTypes(TagType type);
|
||||
void createChildMenu(const ScxmlTag *tag, QMenu *menu, bool addRemove = true);
|
||||
void initChildMenu(TagType tagType, QMenu *menu);
|
||||
ScxmlTag *findChild(const ScxmlTag *tag, TagType childType);
|
||||
ScxmlTag *metadataTag(ScxmlTag *tag, const QString &tagname, bool blockUpdates = false);
|
||||
void findAllChildren(const ScxmlTag *tag, QVector<ScxmlTag*> &children);
|
||||
void findAllTransitionChildren(const ScxmlTag *tag, QVector<ScxmlTag*> &children);
|
||||
void modifyPosition(ScxmlTag *tag, const QPointF &minPos, const QPointF &targetPos);
|
||||
|
||||
} // namespace TagUtils
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
449
src/plugins/scxmleditor/plugin_interface/scxmltypes.h
Normal file
449
src/plugins/scxmleditor/plugin_interface/scxmltypes.h
Normal file
@@ -0,0 +1,449 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
enum TagType {
|
||||
UnknownTag = 0,
|
||||
Metadata,
|
||||
MetadataItem,
|
||||
Scxml,
|
||||
State,
|
||||
Parallel,
|
||||
Transition,
|
||||
InitialTransition,
|
||||
Initial,
|
||||
Final,
|
||||
OnEntry,
|
||||
OnExit,
|
||||
History,
|
||||
Raise,
|
||||
If,
|
||||
ElseIf,
|
||||
Else,
|
||||
Foreach,
|
||||
Log,
|
||||
DataModel,
|
||||
Data,
|
||||
Assign,
|
||||
Donedata,
|
||||
Content,
|
||||
Param,
|
||||
Script,
|
||||
Send,
|
||||
Cancel,
|
||||
Invoke,
|
||||
Finalize
|
||||
};
|
||||
|
||||
struct scxmltag_attribute_t;
|
||||
struct scxmltag_type_t;
|
||||
|
||||
struct scxmltag_attribute_t
|
||||
{
|
||||
const char *name; // scxml attribute name
|
||||
const char *value; // default value
|
||||
bool required;
|
||||
bool editable;
|
||||
int datatype;
|
||||
};
|
||||
|
||||
struct scxmltag_type_t
|
||||
{
|
||||
const char *name; // scxml output name
|
||||
bool canIncludeContent;
|
||||
const scxmltag_attribute_t *attributes;
|
||||
int n_attributes;
|
||||
};
|
||||
|
||||
// Define tag-attributes
|
||||
const scxmltag_attribute_t scxml_scxml_attributes[] = {
|
||||
{ "initial", nullptr, false, false, QVariant::String },
|
||||
{ "name", nullptr, false, true, QVariant::String },
|
||||
{ "xmlns", "http://www.w3.org/2005/07/scxml", true, false, QVariant::String },
|
||||
{ "version", "1.0", true, false, QVariant::String },
|
||||
{ "datamodel", nullptr, false, true, QVariant::String },
|
||||
{ "binding", "early;late", false, true, QVariant::StringList }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_state_attributes[] = {
|
||||
{ "id", nullptr, false, true, QVariant::String },
|
||||
{ "initial", nullptr, false, false, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_parallel_attributes[] = {
|
||||
{ "id", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_transition_attributes[] = {
|
||||
{ "event", nullptr, false, true, QVariant::String },
|
||||
{ "cond", nullptr, false, true, QVariant::String },
|
||||
{ "target", nullptr, false, true, QVariant::String },
|
||||
{ "type", "internal;external", false, true, QVariant::StringList }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_initialtransition_attributes[] = {
|
||||
{ "target", nullptr, false, false, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_final_attributes[] = {
|
||||
{ "id", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_history_attributes[] = {
|
||||
{ "id", nullptr, false, true, QVariant::String },
|
||||
{ "type", "shallow;deep", false, true, QVariant::StringList }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_raise_attributes[] = {
|
||||
{ "event", nullptr, true, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_if_attributes[] = {
|
||||
{ "cond", nullptr, true, true, QVariant::String },
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_elseif_attributes[] = {
|
||||
{ "cond", nullptr, true, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_foreach_attributes[] = {
|
||||
{ "array", nullptr, true, true, QVariant::String },
|
||||
{ "item", nullptr, true, true, QVariant::String },
|
||||
{ "index", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_log_attributes[] = {
|
||||
{ "label", "", false, true, QVariant::String },
|
||||
{ "expr", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_data_attributes[] = {
|
||||
{ "id", nullptr, true, true, QVariant::String },
|
||||
{ "src", nullptr, false, true, QVariant::String },
|
||||
{ "expr", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_assign_attributes[] = {
|
||||
{ "location", nullptr, true, true, QVariant::String },
|
||||
{ "expr", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_content_attributes[] = {
|
||||
{ "expr", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_param_attributes[] = {
|
||||
{ "name", nullptr, true, true, QVariant::String },
|
||||
{ "expr", nullptr, false, true, QVariant::String },
|
||||
{ "location", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_script_attributes[] = {
|
||||
{ "src", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_send_attributes[] = {
|
||||
{ "event", nullptr, false, true, QVariant::String },
|
||||
{ "eventexpr", nullptr, false, true, QVariant::String },
|
||||
{ "target", nullptr, false, true, QVariant::String },
|
||||
{ "targetexpr", nullptr, false, true, QVariant::String },
|
||||
{ "type", nullptr, false, true, QVariant::String },
|
||||
{ "typeexpr", nullptr, false, true, QVariant::String },
|
||||
{ "id", nullptr, false, true, QVariant::String },
|
||||
{ "idiocation", nullptr, false, true, QVariant::String },
|
||||
{ "delay", nullptr, false, true, QVariant::String },
|
||||
{ "delayexpr", nullptr, false, true, QVariant::String },
|
||||
{ "namelist", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_cancel_attributes[] = {
|
||||
{ "sendid", nullptr, false, true, QVariant::String },
|
||||
{ "sendidexpr", nullptr, false, true, QVariant::String }
|
||||
};
|
||||
|
||||
const scxmltag_attribute_t scxml_invoke_attributes[] = {
|
||||
{ "type", nullptr, false, true, QVariant::String },
|
||||
{ "typeexpr", nullptr, false, true, QVariant::String },
|
||||
{ "src", nullptr, false, true, QVariant::String },
|
||||
{ "srcexpr", nullptr, false, true, QVariant::String },
|
||||
{ "id", nullptr, false, true, QVariant::String },
|
||||
{ "idiocation", nullptr, false, true, QVariant::String },
|
||||
{ "namelist", nullptr, false, true, QVariant::String },
|
||||
{ "autoforward", ";true;false", false, true, QVariant::StringList }
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_unknown = {
|
||||
"unknown",
|
||||
true,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_metadata = {
|
||||
"metadata",
|
||||
true,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_metadataitem = {
|
||||
"item",
|
||||
true,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_scxml = {
|
||||
"scxml",
|
||||
false,
|
||||
scxml_scxml_attributes,
|
||||
sizeof(scxml_scxml_attributes) / sizeof(scxml_scxml_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_state = {
|
||||
"state",
|
||||
false,
|
||||
scxml_state_attributes,
|
||||
sizeof(scxml_state_attributes) / sizeof(scxml_state_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_parallel = {
|
||||
"parallel",
|
||||
false,
|
||||
scxml_parallel_attributes,
|
||||
sizeof(scxml_parallel_attributes) / sizeof(scxml_parallel_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_transition = {
|
||||
"transition",
|
||||
false,
|
||||
scxml_transition_attributes,
|
||||
sizeof(scxml_transition_attributes) / sizeof(scxml_transition_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_initialtransition = {
|
||||
"transition",
|
||||
false,
|
||||
scxml_initialtransition_attributes,
|
||||
sizeof(scxml_initialtransition_attributes) / sizeof(scxml_initialtransition_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_initial = {
|
||||
"initial",
|
||||
false,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_final = {
|
||||
"final",
|
||||
false,
|
||||
scxml_final_attributes,
|
||||
sizeof(scxml_final_attributes) / sizeof(scxml_final_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_onentry = {
|
||||
"onentry",
|
||||
false,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_onexit = {
|
||||
"onexit",
|
||||
false,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_history = {
|
||||
"history",
|
||||
false,
|
||||
scxml_history_attributes,
|
||||
sizeof(scxml_history_attributes) / sizeof(scxml_history_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_raise = {
|
||||
"raise",
|
||||
false,
|
||||
scxml_raise_attributes,
|
||||
sizeof(scxml_raise_attributes) / sizeof(scxml_raise_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_if = {
|
||||
"if",
|
||||
false,
|
||||
scxml_if_attributes,
|
||||
sizeof(scxml_if_attributes) / sizeof(scxml_if_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_elseif = {
|
||||
"elseif",
|
||||
false,
|
||||
scxml_elseif_attributes,
|
||||
sizeof(scxml_elseif_attributes) / sizeof(scxml_elseif_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_else = {
|
||||
"else",
|
||||
false,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_foreach = {
|
||||
"foreach",
|
||||
false,
|
||||
scxml_foreach_attributes,
|
||||
sizeof(scxml_foreach_attributes) / sizeof(scxml_foreach_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_log = {
|
||||
"log",
|
||||
false,
|
||||
scxml_log_attributes,
|
||||
sizeof(scxml_log_attributes) / sizeof(scxml_log_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_datamodel = {
|
||||
"datamodel",
|
||||
false,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_data = {
|
||||
"data",
|
||||
false,
|
||||
scxml_data_attributes,
|
||||
sizeof(scxml_data_attributes) / sizeof(scxml_data_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_assign = {
|
||||
"assign",
|
||||
false,
|
||||
scxml_assign_attributes,
|
||||
sizeof(scxml_assign_attributes) / sizeof(scxml_assign_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_donedata = {
|
||||
"donedata",
|
||||
false,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_content = {
|
||||
"content",
|
||||
false,
|
||||
scxml_content_attributes,
|
||||
sizeof(scxml_content_attributes) / sizeof(scxml_content_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_param = {
|
||||
"param",
|
||||
false,
|
||||
scxml_param_attributes,
|
||||
sizeof(scxml_param_attributes) / sizeof(scxml_param_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_script = {
|
||||
"script",
|
||||
true,
|
||||
scxml_script_attributes,
|
||||
sizeof(scxml_script_attributes) / sizeof(scxml_script_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_send = {
|
||||
"send",
|
||||
false,
|
||||
scxml_send_attributes,
|
||||
sizeof(scxml_send_attributes) / sizeof(scxml_send_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_cancel = {
|
||||
"cancel",
|
||||
false,
|
||||
scxml_cancel_attributes,
|
||||
sizeof(scxml_cancel_attributes) / sizeof(scxml_cancel_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_invoke = {
|
||||
"invoke",
|
||||
false,
|
||||
scxml_invoke_attributes,
|
||||
sizeof(scxml_invoke_attributes) / sizeof(scxml_invoke_attributes[0])
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_finalize = {
|
||||
"finalize",
|
||||
false,
|
||||
nullptr,
|
||||
0
|
||||
};
|
||||
|
||||
const scxmltag_type_t scxml_tags[] = {
|
||||
scxml_unknown,
|
||||
scxml_metadata,
|
||||
scxml_metadataitem,
|
||||
scxml_scxml,
|
||||
scxml_state,
|
||||
scxml_parallel,
|
||||
scxml_transition,
|
||||
scxml_initialtransition,
|
||||
scxml_initial,
|
||||
scxml_final,
|
||||
scxml_onentry,
|
||||
scxml_onexit,
|
||||
scxml_history,
|
||||
scxml_raise,
|
||||
scxml_if,
|
||||
scxml_elseif,
|
||||
scxml_else,
|
||||
scxml_foreach,
|
||||
scxml_log,
|
||||
scxml_datamodel,
|
||||
scxml_data,
|
||||
scxml_assign,
|
||||
scxml_donedata,
|
||||
scxml_content,
|
||||
scxml_param,
|
||||
scxml_script,
|
||||
scxml_send,
|
||||
scxml_cancel,
|
||||
scxml_invoke,
|
||||
scxml_finalize
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
126
src/plugins/scxmleditor/plugin_interface/scxmluifactory.cpp
Normal file
126
src/plugins/scxmleditor/plugin_interface/scxmluifactory.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "scxmluifactory.h"
|
||||
#include "genericscxmlplugin.h"
|
||||
#include "isceditor.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QGenericPlugin>
|
||||
#include <QGenericPluginFactory>
|
||||
#include <QPluginLoader>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ScxmlUiFactory::ScxmlUiFactory(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
initPlugins();
|
||||
}
|
||||
|
||||
ScxmlUiFactory::~ScxmlUiFactory()
|
||||
{
|
||||
for (int i = m_plugins.count(); i--;)
|
||||
m_plugins[i]->detach();
|
||||
}
|
||||
|
||||
void ScxmlUiFactory::documentChanged(DocumentChangeType type, ScxmlDocument *doc)
|
||||
{
|
||||
for (int i = 0; i < m_plugins.count(); ++i)
|
||||
m_plugins[i]->documentChanged(type, doc);
|
||||
}
|
||||
|
||||
void ScxmlUiFactory::refresh()
|
||||
{
|
||||
for (int i = 0; i < m_plugins.count(); ++i)
|
||||
m_plugins[i]->refresh();
|
||||
}
|
||||
|
||||
QObject *ScxmlUiFactory::object(const QString &type) const
|
||||
{
|
||||
return m_objects.value(type, 0);
|
||||
}
|
||||
|
||||
void ScxmlUiFactory::unregisterObject(const QString &type, QObject *obj)
|
||||
{
|
||||
if (obj && m_objects[type] == obj)
|
||||
m_objects.take(type);
|
||||
}
|
||||
|
||||
void ScxmlUiFactory::registerObject(const QString &type, QObject *obj)
|
||||
{
|
||||
if (obj)
|
||||
m_objects[type] = obj;
|
||||
}
|
||||
|
||||
bool ScxmlUiFactory::isActive(const QString &type, const QObject *obj) const
|
||||
{
|
||||
return obj && m_objects.value(type, 0) == obj;
|
||||
}
|
||||
|
||||
void ScxmlUiFactory::initPlugins()
|
||||
{
|
||||
// First init general plugin
|
||||
m_plugins << new GenericScxmlPlugin;
|
||||
|
||||
// Get additional plugins
|
||||
QDir pluginDir(QCoreApplication::applicationDirPath() + QDir::separator() + "SCEPlugins");
|
||||
|
||||
QStringList nameFilters;
|
||||
nameFilters << "*.dll" << "*.so";
|
||||
|
||||
foreach (QFileInfo dllFileInfo, pluginDir.entryInfoList(nameFilters)) {
|
||||
|
||||
QPluginLoader loader(dllFileInfo.absoluteFilePath());
|
||||
loader.load();
|
||||
|
||||
if (!loader.isLoaded())
|
||||
break;
|
||||
|
||||
auto plugin = qobject_cast<QGenericPlugin*>(loader.instance());
|
||||
|
||||
if (!plugin)
|
||||
break;
|
||||
|
||||
QObject *instance = plugin->create(QString(), QString());
|
||||
|
||||
if (instance) {
|
||||
auto scEditorInstance = qobject_cast<ISCEditor*>(instance);
|
||||
if (scEditorInstance) {
|
||||
qDebug() << tr("Created editor-instance.");
|
||||
m_plugins << scEditorInstance;
|
||||
} else {
|
||||
qWarning() << tr("Editor-instance is not of the type ISCEditor.");
|
||||
loader.unload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last init plugins
|
||||
for (int i = 0; i < m_plugins.count(); ++i)
|
||||
m_plugins[i]->init(this);
|
||||
}
|
||||
71
src/plugins/scxmleditor/plugin_interface/scxmluifactory.h
Normal file
71
src/plugins/scxmleditor/plugin_interface/scxmluifactory.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "mytypes.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ISCEditor;
|
||||
class ScxmlDocument;
|
||||
|
||||
class ScxmlUiFactory : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScxmlUiFactory(QObject *parent = nullptr);
|
||||
~ScxmlUiFactory() override;
|
||||
|
||||
// Inform document changes
|
||||
void documentChanged(DocumentChangeType type, ScxmlDocument *doc);
|
||||
|
||||
// Inform plugins to refresh
|
||||
void refresh();
|
||||
|
||||
// Get registered objects
|
||||
QObject *object(const QString &type) const;
|
||||
|
||||
// Register objects
|
||||
void unregisterObject(const QString &type, QObject *object);
|
||||
void registerObject(const QString &type, QObject *object);
|
||||
|
||||
// Check is active
|
||||
bool isActive(const QString &type, const QObject *object) const;
|
||||
|
||||
private:
|
||||
void initPlugins();
|
||||
|
||||
QVector<ISCEditor*> m_plugins;
|
||||
QMap<QString, QObject*> m_objects;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
121
src/plugins/scxmleditor/plugin_interface/serializer.cpp
Normal file
121
src/plugins/scxmleditor/plugin_interface/serializer.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "serializer.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
Serializer::Serializer()
|
||||
: m_separator(";")
|
||||
{
|
||||
}
|
||||
|
||||
void Serializer::seek(int pos)
|
||||
{
|
||||
m_index = qBound(0, pos, m_data.count() - 1);
|
||||
}
|
||||
|
||||
void Serializer::clear()
|
||||
{
|
||||
m_data.clear();
|
||||
m_index = 0;
|
||||
}
|
||||
|
||||
void Serializer::append(double d)
|
||||
{
|
||||
m_data.append(QString::fromLatin1("%1").arg(d, 0, 'f', 2).remove(".00"));
|
||||
m_index = m_data.count() - 1;
|
||||
}
|
||||
|
||||
QString Serializer::data() const
|
||||
{
|
||||
return m_data.join(m_separator);
|
||||
}
|
||||
|
||||
void Serializer::append(const QPolygonF &d)
|
||||
{
|
||||
appendPolygon(d);
|
||||
}
|
||||
void Serializer::append(const QPolygon &d)
|
||||
{
|
||||
appendPolygon(d);
|
||||
}
|
||||
void Serializer::append(const QRectF &d)
|
||||
{
|
||||
appendRect(d);
|
||||
}
|
||||
void Serializer::append(const QRect &d)
|
||||
{
|
||||
appendRect(d);
|
||||
}
|
||||
void Serializer::append(const QPointF &d)
|
||||
{
|
||||
appendPoint(d);
|
||||
}
|
||||
void Serializer::append(const QPoint &d)
|
||||
{
|
||||
appendPoint(d);
|
||||
}
|
||||
|
||||
void Serializer::read(QPolygonF &d)
|
||||
{
|
||||
readPolygon<QPointF>(d);
|
||||
}
|
||||
void Serializer::read(QPolygon &d)
|
||||
{
|
||||
readPolygon<QPoint>(d);
|
||||
}
|
||||
void Serializer::read(QRectF &d)
|
||||
{
|
||||
readRect(d);
|
||||
}
|
||||
void Serializer::read(QRect &d)
|
||||
{
|
||||
readRect(d);
|
||||
}
|
||||
void Serializer::read(QPointF &d)
|
||||
{
|
||||
readPoint(d);
|
||||
}
|
||||
void Serializer::read(QPoint &d)
|
||||
{
|
||||
readPoint(d);
|
||||
}
|
||||
|
||||
void Serializer::setData(const QString &d)
|
||||
{
|
||||
m_data = d.split(m_separator, QString::SkipEmptyParts);
|
||||
m_index = 0;
|
||||
}
|
||||
|
||||
double Serializer::readNext()
|
||||
{
|
||||
double data = 0.0;
|
||||
if (m_index >= 0 && m_index < m_data.count())
|
||||
data = m_data[m_index].toDouble();
|
||||
|
||||
m_index++;
|
||||
return data;
|
||||
}
|
||||
133
src/plugins/scxmleditor/plugin_interface/serializer.h
Normal file
133
src/plugins/scxmleditor/plugin_interface/serializer.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QPoint>
|
||||
#include <QPointF>
|
||||
#include <QPolygon>
|
||||
#include <QPolygonF>
|
||||
#include <QRect>
|
||||
#include <QRectF>
|
||||
#include <QStringList>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The Serializer class provides serialization of item-data to the string.
|
||||
*
|
||||
* For example items inside the graphicsview uses this class when they need to save ui-properties to the scxmltag-attribute.
|
||||
*/
|
||||
class Serializer
|
||||
{
|
||||
public:
|
||||
Serializer();
|
||||
|
||||
void seek(int pos);
|
||||
void clear();
|
||||
|
||||
void append(const QPolygonF &d);
|
||||
void append(const QPolygon &d);
|
||||
void append(const QRectF &d);
|
||||
void append(const QRect &d);
|
||||
void append(const QPointF &d);
|
||||
void append(const QPoint &d);
|
||||
|
||||
void read(QPolygonF &d);
|
||||
void read(QPolygon &d);
|
||||
void read(QRectF &d);
|
||||
void read(QRect &d);
|
||||
void read(QPointF &d);
|
||||
void read(QPoint &d);
|
||||
|
||||
void setSeparator(const QString &sep);
|
||||
void setData(const QString &d);
|
||||
QString data() const;
|
||||
|
||||
private:
|
||||
void append(double d);
|
||||
double readNext();
|
||||
|
||||
int m_index = 0;
|
||||
const QString m_separator;
|
||||
QStringList m_data;
|
||||
|
||||
template <class T, class P>
|
||||
void readPolygon(P &d)
|
||||
{
|
||||
int count = (m_data.count() - m_index) / 2;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
T p;
|
||||
read(p);
|
||||
d << p;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void readRect(T &d)
|
||||
{
|
||||
d.setLeft(readNext());
|
||||
d.setTop(readNext());
|
||||
d.setWidth(readNext());
|
||||
d.setHeight(readNext());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void readPoint(T &d)
|
||||
{
|
||||
d.setX(readNext());
|
||||
d.setY(readNext());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void appendPolygon(const T &d)
|
||||
{
|
||||
for (int i = 0; i < d.count(); ++i) {
|
||||
append(d[i].x());
|
||||
append(d[i].y());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void appendPoint(const T &d)
|
||||
{
|
||||
append(d.x());
|
||||
append(d.y());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void appendRect(const T &d)
|
||||
{
|
||||
append(d.left());
|
||||
append(d.top());
|
||||
append(d.width());
|
||||
append(d.height());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
33
src/plugins/scxmleditor/plugin_interface/shapeprovider.cpp
Normal file
33
src/plugins/scxmleditor/plugin_interface/shapeprovider.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "shapeprovider.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
ShapeProvider::ShapeProvider(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
85
src/plugins/scxmleditor/plugin_interface/shapeprovider.h
Normal file
85
src/plugins/scxmleditor/plugin_interface/shapeprovider.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scxmltag.h"
|
||||
#include <QByteArray>
|
||||
#include <QIcon>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ShapeProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct Shape
|
||||
{
|
||||
QString title;
|
||||
QIcon icon;
|
||||
QStringList filters;
|
||||
QByteArray scxmlData;
|
||||
QVariant userData;
|
||||
};
|
||||
|
||||
struct ShapeGroup
|
||||
{
|
||||
~ShapeGroup()
|
||||
{
|
||||
qDeleteAll(shapes);
|
||||
shapes.clear();
|
||||
}
|
||||
|
||||
QString title;
|
||||
QVector<Shape*> shapes;
|
||||
void addShape(Shape *shape)
|
||||
{
|
||||
shapes << shape;
|
||||
}
|
||||
};
|
||||
|
||||
explicit ShapeProvider(QObject *parent = nullptr);
|
||||
|
||||
virtual int groupCount() const = 0;
|
||||
virtual QString groupTitle(int groupIndex) const = 0;
|
||||
|
||||
virtual int shapeCount(int groupIndex) const = 0;
|
||||
virtual QString shapeTitle(int groupIndex, int shapeIndex) const = 0;
|
||||
virtual QIcon shapeIcon(int groupIndex, int shapeIndex) const = 0;
|
||||
|
||||
virtual bool canDrop(int groupIndex, int shapeIndex, ScxmlTag *parent) const = 0;
|
||||
virtual QByteArray scxmlCode(int groupIndex, int shapeIndex, ScxmlTag *parent) const = 0;
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
57
src/plugins/scxmleditor/plugin_interface/snapline.cpp
Normal file
57
src/plugins/scxmleditor/plugin_interface/snapline.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "snapline.h"
|
||||
#include <QPen>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
SnapLine::SnapLine(QGraphicsItem *parent)
|
||||
: QGraphicsLineItem(parent)
|
||||
{
|
||||
QPen pen;
|
||||
pen.setBrush(QColor(0x22, 0xcc, 0x22));
|
||||
pen.setStyle(Qt::DashLine);
|
||||
setPen(pen);
|
||||
setZValue(502);
|
||||
|
||||
m_visibilityTimer.setInterval(1000);
|
||||
m_visibilityTimer.setSingleShot(true);
|
||||
QObject::connect(&m_visibilityTimer, &QTimer::timeout, this, &SnapLine::hideLine);
|
||||
|
||||
hideLine();
|
||||
}
|
||||
|
||||
void SnapLine::show(qreal x1, qreal y1, qreal x2, qreal y2)
|
||||
{
|
||||
setLine(x1, y1, x2, y2);
|
||||
setVisible(true);
|
||||
m_visibilityTimer.start();
|
||||
}
|
||||
|
||||
void SnapLine::hideLine()
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
50
src/plugins/scxmleditor/plugin_interface/snapline.h
Normal file
50
src/plugins/scxmleditor/plugin_interface/snapline.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsLineItem>
|
||||
#include <QTimer>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class SnapLine : public QObject, public QGraphicsLineItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SnapLine(QGraphicsItem *parent = nullptr);
|
||||
|
||||
void show(qreal x1, qreal y1, qreal x2, qreal y2);
|
||||
void hideLine();
|
||||
|
||||
private:
|
||||
QTimer m_visibilityTimer;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
581
src/plugins/scxmleditor/plugin_interface/stateitem.cpp
Normal file
581
src/plugins/scxmleditor/plugin_interface/stateitem.cpp
Normal file
@@ -0,0 +1,581 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "stateitem.h"
|
||||
#include "finalstateitem.h"
|
||||
#include "graphicsitemprovider.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "idwarningitem.h"
|
||||
#include "imageprovider.h"
|
||||
#include "initialstateitem.h"
|
||||
#include "parallelitem.h"
|
||||
#include "sceneutils.h"
|
||||
#include "scxmleditorconstants.h"
|
||||
#include "scxmltagutils.h"
|
||||
#include "scxmluifactory.h"
|
||||
#include "statewarningitem.h"
|
||||
#include "textitem.h"
|
||||
#include "transitionitem.h"
|
||||
#include "utilsprovider.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
#include <QTextOption>
|
||||
#include <QUndoStack>
|
||||
#include <QtMath>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
const qreal TEXT_ITEM_HEIGHT = 20;
|
||||
const qreal TEXT_ITEM_CAP = 10;
|
||||
const qreal STATE_RADIUS = 10;
|
||||
|
||||
StateItem::StateItem(const QPointF &pos, BaseItem *parent)
|
||||
: ConnectableItem(pos, parent)
|
||||
{
|
||||
m_stateNameItem = new TextItem(this);
|
||||
m_stateNameItem->setParentItem(this);
|
||||
|
||||
checkWarningItems();
|
||||
|
||||
connect(m_stateNameItem, &TextItem::selected, this, [=](bool sel){
|
||||
setItemSelected(sel);
|
||||
});
|
||||
connect(m_stateNameItem, &TextItem::textChanged, this, &StateItem::updateTextPositions);
|
||||
connect(m_stateNameItem, &TextItem::textReady, this, &StateItem::titleHasChanged);
|
||||
|
||||
m_pen = QPen(QColor(0x45, 0x45, 0x45));
|
||||
|
||||
updateColors();
|
||||
updatePolygon();
|
||||
}
|
||||
|
||||
void StateItem::checkWarningItems()
|
||||
{
|
||||
ScxmlUiFactory *uifactory = uiFactory();
|
||||
if (uifactory) {
|
||||
auto provider = static_cast<GraphicsItemProvider*>(uifactory->object("graphicsItemProvider"));
|
||||
if (provider) {
|
||||
if (!m_idWarningItem)
|
||||
m_idWarningItem = static_cast<IdWarningItem*>(provider->createWarningItem(Constants::C_STATE_WARNING_ID, this));
|
||||
if (!m_stateWarningItem)
|
||||
m_stateWarningItem = static_cast<StateWarningItem*>(provider->createWarningItem(Constants::C_STATE_WARNING_STATE, this));
|
||||
|
||||
if (m_idWarningItem && m_stateWarningItem)
|
||||
m_stateWarningItem->setIdWarning(m_idWarningItem);
|
||||
|
||||
checkWarnings();
|
||||
|
||||
if (m_idWarningItem || m_stateWarningItem)
|
||||
updateAttributes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariant StateItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
QVariant retValue = ConnectableItem::itemChange(change, value);
|
||||
|
||||
switch (change) {
|
||||
case QGraphicsItem::ItemSceneHasChanged:
|
||||
checkWarningItems();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
void StateItem::updateAttributes()
|
||||
{
|
||||
if (tag()) {
|
||||
ConnectableItem::updateAttributes();
|
||||
|
||||
// Check initial attribute
|
||||
QString strNewId = tagValue("id", true);
|
||||
if (!m_parallelState) {
|
||||
QStringList NSIDs = strNewId.split(tag()->document()->nameSpaceDelimiter(), QString::SkipEmptyParts);
|
||||
if (NSIDs.count() > 0) {
|
||||
NSIDs[NSIDs.count() - 1] = m_stateNameItem->toPlainText();
|
||||
QString strOldId = NSIDs.join(tag()->document()->nameSpaceDelimiter());
|
||||
ScxmlTag *parentTag = tag()->parentTag();
|
||||
if (parentTag && !strOldId.isEmpty() && parentTag->attribute("initial") == strOldId)
|
||||
parentTag->setAttribute("initial", strNewId);
|
||||
}
|
||||
}
|
||||
|
||||
m_stateNameItem->setText(tagValue("id"));
|
||||
if (m_idWarningItem)
|
||||
m_idWarningItem->setId(strNewId);
|
||||
updateTextPositions();
|
||||
|
||||
if (m_parallelState)
|
||||
checkInitial(true);
|
||||
}
|
||||
|
||||
updateBoundingRect();
|
||||
}
|
||||
|
||||
void StateItem::updateEditorInfo(bool allChildren)
|
||||
{
|
||||
ConnectableItem::updateEditorInfo(allChildren);
|
||||
|
||||
QString color = editorInfo(Constants::C_SCXML_EDITORINFO_FONTCOLOR);
|
||||
m_stateNameItem->setDefaultTextColor(color.isEmpty() ? QColor(Qt::black) : QColor(color));
|
||||
|
||||
// Update child too if necessary
|
||||
if (allChildren) {
|
||||
QList<QGraphicsItem*> children = childItems();
|
||||
for (int i = 0; i < children.count(); ++i) {
|
||||
if (children[i]->type() >= InitialStateType) {
|
||||
auto child = qgraphicsitem_cast<BaseItem*>(children[i]);
|
||||
if (child)
|
||||
child->updateEditorInfo(allChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateItem::updateColors()
|
||||
{
|
||||
updateDepth();
|
||||
m_parallelState = parentItem() && parentItem()->type() == ParallelType;
|
||||
|
||||
if (m_parallelState)
|
||||
m_pen.setStyle(Qt::DashLine);
|
||||
else
|
||||
m_pen.setStyle(Qt::SolidLine);
|
||||
|
||||
// Update child color-indices too
|
||||
QList<QGraphicsItem*> children = childItems();
|
||||
for (int i = 0; i < children.count(); ++i) {
|
||||
if (children[i]->type() >= StateType) {
|
||||
auto child = qgraphicsitem_cast<StateItem*>(children[i]);
|
||||
if (child)
|
||||
child->updateColors();
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void StateItem::updateBoundingRect()
|
||||
{
|
||||
QRectF r2 = childItemsBoundingRect();
|
||||
|
||||
// Check if we need to increase parent boundingrect
|
||||
if (!r2.isNull()) {
|
||||
QRectF r = boundingRect();
|
||||
QRectF r3 = r.united(r2);
|
||||
|
||||
if (r != r3) {
|
||||
setItemBoundingRect(r3);
|
||||
updateTransitions();
|
||||
updateUIProperties();
|
||||
checkOverlapping();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateItem::shrink()
|
||||
{
|
||||
QRectF trect;
|
||||
foreach (TransitionItem *item, outputTransitions()) {
|
||||
if (item->targetType() == TransitionItem::InternalSameTarget || item->targetType() == TransitionItem::InternalNoTarget) {
|
||||
trect = trect.united(item->wholeBoundingRect());
|
||||
}
|
||||
}
|
||||
|
||||
QRectF r = boundingRect();
|
||||
QRectF r2 = childItemsBoundingRect();
|
||||
double minWidth = qMax(120.0, r2.width());
|
||||
double minH = qMax((double)minHeight(), r2.height());
|
||||
minWidth = qMax(minWidth, m_stateNameItem->boundingRect().width() + (double)WARNING_ITEM_SIZE + (double)TEXT_ITEM_CAP);
|
||||
|
||||
if (!m_backgroundImage.isNull()) {
|
||||
minWidth = qMax(minWidth, (double)m_backgroundImage.width() + 3 * STATE_RADIUS + trect.width());
|
||||
minH = qMax(minH, ((double)m_backgroundImage.height() + 3 * STATE_RADIUS + TEXT_ITEM_HEIGHT) / 0.94);
|
||||
}
|
||||
|
||||
r2 = QRectF(0, 0, minWidth, minH);
|
||||
r2.moveCenter(r.center());
|
||||
|
||||
// Check if we need to increase parent boundingrect
|
||||
if (r != r2) {
|
||||
setItemBoundingRect(r2);
|
||||
updateTransitions();
|
||||
updateUIProperties();
|
||||
}
|
||||
}
|
||||
|
||||
void StateItem::transitionsChanged()
|
||||
{
|
||||
QRectF rr = boundingRect();
|
||||
QRectF rectInternalTransitions;
|
||||
QVector<TransitionItem*> internalTransitions = outputTransitions();
|
||||
foreach (TransitionItem *item, internalTransitions) {
|
||||
if (item->targetType() <= TransitionItem::InternalNoTarget) {
|
||||
QRectF br = mapFromItem(item, item->boundingRect()).boundingRect();
|
||||
br.setLeft(rr.left() + 20);
|
||||
br.setTop(br.top() + 4);
|
||||
br.setWidth(br.width() + item->textWidth());
|
||||
rectInternalTransitions = rectInternalTransitions.united(br);
|
||||
}
|
||||
}
|
||||
|
||||
m_transitionRect = rectInternalTransitions;
|
||||
updateBoundingRect();
|
||||
}
|
||||
|
||||
void StateItem::transitionCountChanged()
|
||||
{
|
||||
ConnectableItem::transitionsChanged();
|
||||
checkWarnings();
|
||||
transitionsChanged();
|
||||
}
|
||||
|
||||
QRectF StateItem::childItemsBoundingRect() const
|
||||
{
|
||||
QRectF r;
|
||||
QRectF rr = boundingRect();
|
||||
|
||||
QList<QGraphicsItem*> children = childItems();
|
||||
for (int i = 0; i < children.count(); ++i) {
|
||||
if (children[i]->type() >= InitialStateType) {
|
||||
QRectF br = children[i]->boundingRect();
|
||||
QPointF p = children[i]->pos() + br.topLeft();
|
||||
br.moveTopLeft(p);
|
||||
r = r.united(br);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_transitionRect.isValid()) {
|
||||
r.setLeft(r.left() - m_transitionRect.width());
|
||||
r.setHeight(qMax(r.height(), m_transitionRect.height()));
|
||||
r.moveBottom(qMax(r.bottom(), m_transitionRect.bottom()));
|
||||
}
|
||||
|
||||
if (!r.isNull())
|
||||
r.adjust(-20, -(rr.height() * 0.06 + 40), 20, 20);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void StateItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
ConnectableItem::mouseDoubleClickEvent(event);
|
||||
shrink();
|
||||
updateUIProperties();
|
||||
}
|
||||
|
||||
void StateItem::createContextMenu(QMenu *menu)
|
||||
{
|
||||
QVariantMap data;
|
||||
if (!m_parallelState) {
|
||||
data[Constants::C_SCXMLTAG_ACTIONTYPE] = TagUtils::SetAsInitial;
|
||||
menu->addAction(tr("Set as Initial"))->setData(data);
|
||||
}
|
||||
|
||||
data[Constants::C_SCXMLTAG_ACTIONTYPE] = TagUtils::ZoomToState;
|
||||
menu->addAction(tr("Zoom to State"))->setData(data);
|
||||
|
||||
if (type() == ParallelType) {
|
||||
data[Constants::C_SCXMLTAG_ACTIONTYPE] = TagUtils::Relayout;
|
||||
menu->addAction(tr("Relayout"))->setData(data);
|
||||
}
|
||||
|
||||
menu->addSeparator();
|
||||
ConnectableItem::createContextMenu(menu);
|
||||
}
|
||||
|
||||
void StateItem::selectedMenuAction(const QAction *action)
|
||||
{
|
||||
if (!action)
|
||||
return;
|
||||
|
||||
const ScxmlTag *tag = this->tag();
|
||||
|
||||
if (tag) {
|
||||
const QVariantMap data = action->data().toMap();
|
||||
const int actionType = data.value(Constants::C_SCXMLTAG_ACTIONTYPE, -1).toInt();
|
||||
|
||||
ScxmlDocument *document = tag->document();
|
||||
switch (actionType) {
|
||||
case TagUtils::SetAsInitial: {
|
||||
ScxmlTag *parentTag = tag->parentTag();
|
||||
if (parentTag) {
|
||||
document->undoStack()->beginMacro(tr("Change initial-state"));
|
||||
|
||||
ScxmlTag *initialTag = parentTag->child("initial");
|
||||
if (initialTag) {
|
||||
ScxmlTag *initialTransitionTag = initialTag->child("transition");
|
||||
if (initialTransitionTag)
|
||||
document->setValue(initialTransitionTag, "target", tag->attribute("id", true));
|
||||
else {
|
||||
auto newTransition = new ScxmlTag(Transition, document);
|
||||
newTransition->setAttribute("target", tag->attribute("id", true));
|
||||
document->addTag(initialTag, newTransition);
|
||||
}
|
||||
} else
|
||||
document->setValue(parentTag, "initial", tag->attribute("id", true));
|
||||
|
||||
checkInitial(true);
|
||||
document->undoStack()->endMacro();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TagUtils::Relayout: {
|
||||
document->undoStack()->beginMacro(tr("Relayout"));
|
||||
doLayout(depth());
|
||||
document->undoStack()->endMacro();
|
||||
break;
|
||||
}
|
||||
case TagUtils::ZoomToState: {
|
||||
emit BaseItem::openToDifferentView(this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ConnectableItem::selectedMenuAction(action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateItem::checkInitial(bool parent)
|
||||
{
|
||||
QList<QGraphicsItem*> items;
|
||||
ScxmlTag *tag = nullptr;
|
||||
|
||||
if (parent) {
|
||||
if (parentItem()) {
|
||||
items = parentItem()->childItems();
|
||||
if (parentBaseItem())
|
||||
tag = parentBaseItem()->tag();
|
||||
} else {
|
||||
auto sc = static_cast<GraphicsScene*>(scene());
|
||||
if (sc) {
|
||||
sc->checkInitialState();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
items = childItems();
|
||||
tag = this->tag();
|
||||
}
|
||||
|
||||
if (items.count() > 0 && tag && uiFactory()) {
|
||||
auto utilsProvider = static_cast<UtilsProvider*>(uiFactory()->object("utilsProvider"));
|
||||
if (utilsProvider)
|
||||
utilsProvider->checkInitialState(items, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void StateItem::titleHasChanged(const QString &text)
|
||||
{
|
||||
QString strOldId = tagValue("id", true);
|
||||
setTagValue("id", text);
|
||||
|
||||
// Check initial attribute
|
||||
if (tag() && !m_parallelState) {
|
||||
ScxmlTag *parentTag = tag()->parentTag();
|
||||
if (!strOldId.isEmpty() && parentTag->attribute("initial") == strOldId)
|
||||
parentTag->setAttribute("initial", tagValue("id", true));
|
||||
}
|
||||
}
|
||||
|
||||
void StateItem::updateTextPositions()
|
||||
{
|
||||
if (m_parallelState) {
|
||||
m_stateNameItem->setPos(m_titleRect.x(), m_titleRect.top());
|
||||
m_stateNameItem->setItalic(true);
|
||||
} else {
|
||||
m_stateNameItem->setPos(m_titleRect.center().x() - m_stateNameItem->boundingRect().width() / 2, m_titleRect.top());
|
||||
m_stateNameItem->setItalic(false);
|
||||
}
|
||||
|
||||
QPointF p(m_stateNameItem->pos().x() - WARNING_ITEM_SIZE, m_titleRect.center().y() - WARNING_ITEM_SIZE / 2);
|
||||
if (m_idWarningItem)
|
||||
m_idWarningItem->setPos(p);
|
||||
if (m_stateWarningItem)
|
||||
m_stateWarningItem->setPos(p);
|
||||
}
|
||||
|
||||
void StateItem::updatePolygon()
|
||||
{
|
||||
m_drawingRect = boundingRect().adjusted(5, 5, -5, -5);
|
||||
|
||||
m_polygon.clear();
|
||||
m_polygon << m_drawingRect.topLeft()
|
||||
<< m_drawingRect.topRight()
|
||||
<< m_drawingRect.bottomRight()
|
||||
<< m_drawingRect.bottomLeft()
|
||||
<< m_drawingRect.topLeft();
|
||||
|
||||
m_titleRect = QRectF(m_drawingRect.left(), m_drawingRect.top(), m_drawingRect.width(), TEXT_ITEM_HEIGHT + m_drawingRect.height() * 0.06);
|
||||
QFont f = m_stateNameItem->font();
|
||||
f.setPixelSize(m_titleRect.height() * 0.65);
|
||||
m_stateNameItem->setFont(f);
|
||||
|
||||
updateTextPositions();
|
||||
}
|
||||
|
||||
bool StateItem::canStartTransition(ItemType /*type*/) const
|
||||
{
|
||||
return !m_parallelState;
|
||||
}
|
||||
|
||||
void StateItem::connectToParent(BaseItem *parentItem)
|
||||
{
|
||||
ConnectableItem::connectToParent(parentItem);
|
||||
updateTextPositions();
|
||||
checkInitial(true);
|
||||
}
|
||||
|
||||
void StateItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
ConnectableItem::paint(painter, option, widget);
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
|
||||
// Set opacity and color
|
||||
painter->setOpacity(getOpacity());
|
||||
m_pen.setColor(overlapping() ? qRgb(0xff, 0x00, 0x60) : qRgb(0x45, 0x45, 0x45));
|
||||
painter->setPen(m_pen);
|
||||
QColor stateColor(editorInfo(Constants::C_SCXML_EDITORINFO_STATECOLOR));
|
||||
if (!stateColor.isValid())
|
||||
stateColor = tag() ? tag()->document()->getColor(depth()) : QColor(0x12, 0x34, 0x56);
|
||||
|
||||
// Draw basic frame
|
||||
QRectF r = boundingRect();
|
||||
QLinearGradient grad(r.topLeft(), r.bottomLeft());
|
||||
grad.setColorAt(0, stateColor.lighter(115));
|
||||
grad.setColorAt(1, stateColor);
|
||||
painter->setBrush(QBrush(grad));
|
||||
|
||||
painter->drawRoundedRect(m_drawingRect, STATE_RADIUS, STATE_RADIUS);
|
||||
|
||||
// Background image
|
||||
ScxmlUiFactory *uifactory = uiFactory();
|
||||
if (uifactory) {
|
||||
auto imageProvider = static_cast<ImageProvider*>(uifactory->object("imageProvider"));
|
||||
if (imageProvider) {
|
||||
const QImage *image = imageProvider->backgroundImage(tag());
|
||||
if (image) {
|
||||
int w = m_drawingRect.width() - 2 * STATE_RADIUS;
|
||||
int h = m_drawingRect.height() - m_titleRect.height() - 2 * STATE_RADIUS;
|
||||
int left = m_drawingRect.left() + STATE_RADIUS;
|
||||
int top = m_drawingRect.top() + m_titleRect.height() + STATE_RADIUS;
|
||||
if (m_transitionRect.isValid()) {
|
||||
w = m_drawingRect.right() - m_transitionRect.right() - 2 * STATE_RADIUS;
|
||||
left = m_transitionRect.right() + STATE_RADIUS;
|
||||
}
|
||||
|
||||
m_backgroundImage = image->scaled(w, h, Qt::KeepAspectRatio);
|
||||
painter->drawImage(QPointF(left + (w - m_backgroundImage.width()) / 2, top + (h - m_backgroundImage.height()) / 2), m_backgroundImage);
|
||||
} else
|
||||
m_backgroundImage = QImage();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw title rect
|
||||
if (!m_parallelState) {
|
||||
painter->drawLine(QLineF(m_titleRect.bottomLeft(), m_titleRect.bottomRight()));
|
||||
|
||||
if (m_initial) {
|
||||
double size = m_titleRect.height() * 0.3;
|
||||
painter->setBrush(QColor(0x4d, 0x4d, 0x4d));
|
||||
painter->drawEllipse(QPointF(m_titleRect.left() + 2 * size, m_titleRect.center().y()), size, size);
|
||||
}
|
||||
}
|
||||
|
||||
// Transition part
|
||||
if (m_transitionRect.isValid()) {
|
||||
qreal tx = m_transitionRect.right();
|
||||
painter->drawLine(QLineF(QPointF(tx, m_titleRect.bottom() + STATE_RADIUS), QPointF(tx, m_drawingRect.bottom() - STATE_RADIUS)));
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void StateItem::init(ScxmlTag *tag, BaseItem *parentItem, bool initChildren, bool blockUpdates)
|
||||
{
|
||||
setBlockUpdates(blockUpdates);
|
||||
ConnectableItem::init(tag, parentItem);
|
||||
|
||||
if (initChildren) {
|
||||
for (int i = 0; i < tag->childCount(); ++i) {
|
||||
ScxmlTag *child = tag->child(i);
|
||||
ConnectableItem *newItem = SceneUtils::createItemByTagType(child->tagType(), QPointF());
|
||||
if (newItem) {
|
||||
newItem->init(child, this, initChildren, blockUpdates);
|
||||
newItem->finalizeCreation();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (blockUpdates)
|
||||
setBlockUpdates(false);
|
||||
}
|
||||
|
||||
QString StateItem::itemId() const
|
||||
{
|
||||
return m_stateNameItem ? m_stateNameItem->toPlainText() : QString();
|
||||
}
|
||||
|
||||
void StateItem::doLayout(int d)
|
||||
{
|
||||
if (depth() != d)
|
||||
return;
|
||||
|
||||
SceneUtils::layout(childItems());
|
||||
updateBoundingRect();
|
||||
shrink();
|
||||
}
|
||||
|
||||
void StateItem::setInitial(bool initial)
|
||||
{
|
||||
m_initial = initial;
|
||||
update();
|
||||
checkWarnings();
|
||||
}
|
||||
|
||||
void StateItem::checkWarnings()
|
||||
{
|
||||
if (m_idWarningItem)
|
||||
m_idWarningItem->check();
|
||||
if (m_stateWarningItem)
|
||||
m_stateWarningItem->check();
|
||||
|
||||
if (parentItem() && parentItem()->type() == StateType)
|
||||
qgraphicsitem_cast<StateItem*>(parentItem())->checkWarnings();
|
||||
}
|
||||
|
||||
bool StateItem::isInitial() const
|
||||
{
|
||||
return m_initial;
|
||||
}
|
||||
105
src/plugins/scxmleditor/plugin_interface/stateitem.h
Normal file
105
src/plugins/scxmleditor/plugin_interface/stateitem.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "connectableitem.h"
|
||||
#include <QPen>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QGraphicsSceneMouseEvent)
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class TransitionItem;
|
||||
class TextItem;
|
||||
class IdWarningItem;
|
||||
class StateWarningItem;
|
||||
|
||||
/**
|
||||
* @brief The StateItem class represents the SCXML-State.
|
||||
*/
|
||||
class StateItem : public ConnectableItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StateItem(const QPointF &pos = QPointF(), BaseItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return StateType;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
QString itemId() const;
|
||||
void init(ScxmlTag *tag, BaseItem *parentItem = nullptr, bool initChildren = true, bool blockUpdates = false) override;
|
||||
void updateBoundingRect();
|
||||
void updateAttributes() override;
|
||||
void updateEditorInfo(bool allChildren = false) override;
|
||||
void updateColors() override;
|
||||
virtual void doLayout(int d) override;
|
||||
void shrink();
|
||||
void setInitial(bool initial);
|
||||
bool isInitial() const;
|
||||
void checkWarnings() override;
|
||||
void checkInitial(bool parent = false) override;
|
||||
QRectF childItemsBoundingRect() const;
|
||||
void connectToParent(BaseItem *parentItem) override;
|
||||
|
||||
protected:
|
||||
void updatePolygon() override;
|
||||
void transitionsChanged() override;
|
||||
void transitionCountChanged() override;
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
bool canStartTransition(ItemType type) const override;
|
||||
void createContextMenu(QMenu *menu) override;
|
||||
void selectedMenuAction(const QAction *action) override;
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void writeStateProperties(const QString &tag, QXmlStreamWriter &xml);
|
||||
|
||||
QRectF m_drawingRect;
|
||||
QRectF m_titleRect;
|
||||
QRectF m_transitionRect;
|
||||
|
||||
private:
|
||||
void titleHasChanged(const QString &text);
|
||||
void updateTextPositions();
|
||||
void checkParentBoundingRect();
|
||||
void checkWarningItems();
|
||||
|
||||
TextItem *m_stateNameItem;
|
||||
StateWarningItem *m_stateWarningItem = nullptr;
|
||||
IdWarningItem *m_idWarningItem = nullptr;
|
||||
QPen m_pen;
|
||||
bool m_initial = false;
|
||||
bool m_parallelState = false;
|
||||
QImage m_backgroundImage;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,74 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "statewarningitem.h"
|
||||
#include "idwarningitem.h"
|
||||
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
StateWarningItem::StateWarningItem(StateItem *parent)
|
||||
: WarningItem(parent)
|
||||
{
|
||||
setSeverity(OutputPane::Warning::InfoType);
|
||||
setTypeName(tr("State"));
|
||||
setDescription(tr("Draw some transitions to state."));
|
||||
|
||||
setPixmap(Utils::Icons::WARNING.pixmap());
|
||||
setReason(tr("No input connection"));
|
||||
}
|
||||
|
||||
void StateWarningItem::setIdWarning(IdWarningItem *idwarning)
|
||||
{
|
||||
m_idWarningItem = idwarning;
|
||||
}
|
||||
|
||||
void StateWarningItem::check()
|
||||
{
|
||||
if (m_parentItem) {
|
||||
if (m_idWarningItem && m_idWarningItem->isVisible())
|
||||
setWarningActive(false);
|
||||
else {
|
||||
bool outputProblem = !m_parentItem->hasOutputTransitions(m_parentItem, true);
|
||||
bool inputProblem = !m_parentItem->isInitial() && !m_parentItem->hasInputTransitions(m_parentItem, true);
|
||||
|
||||
if (outputProblem && inputProblem) {
|
||||
setReason(tr("No input or output connections (%1)").arg(m_parentItem->itemId()));
|
||||
setDescription(tr("Draw some transitions to or from state."));
|
||||
setWarningActive(true);
|
||||
} else if (outputProblem) {
|
||||
setReason(tr("No output connections (%1)").arg(m_parentItem->itemId()));
|
||||
setDescription(tr("Draw some transitions from state."));
|
||||
setWarningActive(true);
|
||||
} else if (inputProblem) {
|
||||
setReason(tr("No input connections (%1)").arg(m_parentItem->itemId()));
|
||||
setDescription(tr("Draw some transitions to state."));
|
||||
setWarningActive(true);
|
||||
} else
|
||||
setWarningActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
63
src/plugins/scxmleditor/plugin_interface/statewarningitem.h
Normal file
63
src/plugins/scxmleditor/plugin_interface/statewarningitem.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stateitem.h"
|
||||
#include "warningitem.h"
|
||||
#include <QPointer>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class IdWarningItem;
|
||||
|
||||
/**
|
||||
* @brief The StateWarningItem class
|
||||
*/
|
||||
class StateWarningItem : public WarningItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StateWarningItem(StateItem *parent = nullptr);
|
||||
|
||||
void setIdWarning(IdWarningItem *idwarning);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return StateWarningType;
|
||||
}
|
||||
|
||||
void check() override;
|
||||
|
||||
private:
|
||||
QPointer<IdWarningItem> m_idWarningItem;
|
||||
StateItem *m_parentItem = nullptr;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
143
src/plugins/scxmleditor/plugin_interface/tagtextitem.cpp
Normal file
143
src/plugins/scxmleditor/plugin_interface/tagtextitem.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "tagtextitem.h"
|
||||
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneHoverEvent>
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
TagTextItem::TagTextItem(QGraphicsItem *parent)
|
||||
: QGraphicsObject(parent)
|
||||
{
|
||||
setFlag(ItemIsMovable, true);
|
||||
setFlag(ItemIsFocusable, true);
|
||||
setFlag(ItemIsSelectable, true);
|
||||
m_textItem = new TextItem(this);
|
||||
connect(m_textItem, &TextItem::textChanged, this, [=](){
|
||||
emit textChanged();
|
||||
});
|
||||
connect(m_textItem, &TextItem::textReady, this, [=](const QString &text){
|
||||
emit textReady(text);
|
||||
});
|
||||
connect(m_textItem, &TextItem::selected, this, [=](bool sel){
|
||||
emit selected(sel);
|
||||
});
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
QRectF TagTextItem::boundingRect() const
|
||||
{
|
||||
return m_textItem->boundingRect().adjusted(-8, -8, 8, 8);
|
||||
}
|
||||
|
||||
void TagTextItem::setText(const QString &text)
|
||||
{
|
||||
m_textItem->setText(text);
|
||||
}
|
||||
|
||||
void TagTextItem::setDefaultTextColor(const QColor &col)
|
||||
{
|
||||
m_textItem->setDefaultTextColor(col);
|
||||
}
|
||||
|
||||
bool TagTextItem::needIgnore(const QPointF sPos)
|
||||
{
|
||||
// If we found QuickTransition-item or CornerGrabber at this point, we must ignore mouse press here
|
||||
// So we can press QuickTransition/CornerGrabber item although there is transition lines front of these items
|
||||
foreach (QGraphicsItem *item, scene()->items(sPos)) {
|
||||
if (item->type() == QuickTransitionType || (item->type() == CornerGrabberType && item->parentItem() != this))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TagTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
if (needIgnore(e->scenePos())) {
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
setCursor(Qt::SizeAllCursor);
|
||||
QGraphicsObject::hoverEnterEvent(e);
|
||||
}
|
||||
|
||||
void TagTextItem::hoverMoveEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
if (needIgnore(e->scenePos())) {
|
||||
setCursor(Qt::ArrowCursor);
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
setCursor(Qt::SizeAllCursor);
|
||||
QGraphicsObject::hoverEnterEvent(e);
|
||||
}
|
||||
|
||||
void TagTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
setCursor(Qt::ArrowCursor);
|
||||
QGraphicsObject::hoverLeaveEvent(e);
|
||||
}
|
||||
|
||||
void TagTextItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
|
||||
{
|
||||
if (needIgnore(e->scenePos())) {
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
m_startPos = pos();
|
||||
QGraphicsObject::mousePressEvent(e);
|
||||
}
|
||||
|
||||
void TagTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *e)
|
||||
{
|
||||
m_movePoint += (pos() - m_startPos);
|
||||
emit movePointChanged();
|
||||
QGraphicsObject::mouseReleaseEvent(e);
|
||||
}
|
||||
|
||||
void TagTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(painter)
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(widget)
|
||||
}
|
||||
|
||||
void TagTextItem::resetMovePoint(const QPointF &point)
|
||||
{
|
||||
m_movePoint = point;
|
||||
}
|
||||
|
||||
QPointF TagTextItem::movePoint() const
|
||||
{
|
||||
return m_movePoint;
|
||||
}
|
||||
82
src/plugins/scxmleditor/plugin_interface/tagtextitem.h
Normal file
82
src/plugins/scxmleditor/plugin_interface/tagtextitem.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "textitem.h"
|
||||
#include <QGraphicsObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The TagTextItem class provides the movable and editable text-item.
|
||||
*/
|
||||
class TagTextItem : public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TagTextItem(QGraphicsItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return TagTextType;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
||||
QRectF boundingRect() const override;
|
||||
|
||||
void setText(const QString &text);
|
||||
void setDefaultTextColor(const QColor &col);
|
||||
|
||||
void resetMovePoint(const QPointF &p = QPointF(0, 0));
|
||||
QPointF movePoint() const;
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *e) override;
|
||||
|
||||
signals:
|
||||
void textChanged();
|
||||
void textReady(const QString &text);
|
||||
void selected(bool sel);
|
||||
void movePointChanged();
|
||||
|
||||
private:
|
||||
bool needIgnore(const QPointF sPos);
|
||||
|
||||
QPointF m_movePoint;
|
||||
QPointF m_startPos;
|
||||
TextItem *m_textItem;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
194
src/plugins/scxmleditor/plugin_interface/textitem.cpp
Normal file
194
src/plugins/scxmleditor/plugin_interface/textitem.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "textitem.h"
|
||||
#include <QCursor>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QTextCursor>
|
||||
#include <QTextDocument>
|
||||
#include <QTextOption>
|
||||
#include <qmath.h>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
TextItem::TextItem(QGraphicsItem *parent)
|
||||
: QGraphicsTextItem(parent)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
TextItem::TextItem(const QString &id, QGraphicsItem *parent)
|
||||
: QGraphicsTextItem(id, parent)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void TextItem::init()
|
||||
{
|
||||
setTextInteractionFlags(Qt::TextEditorInteraction);
|
||||
setFlag(ItemIsSelectable, true);
|
||||
setFlag(ItemIsFocusable, true);
|
||||
|
||||
QTextOption options;
|
||||
options.setWrapMode(QTextOption::NoWrap);
|
||||
options.setAlignment(Qt::AlignCenter);
|
||||
document()->setDefaultTextOption(options);
|
||||
|
||||
connect(document(), &QTextDocument::contentsChanged, this, &TextItem::checkText);
|
||||
|
||||
QFont f = font();
|
||||
f.setPixelSize(13);
|
||||
setFont(f);
|
||||
}
|
||||
|
||||
void TextItem::setItalic(bool ital)
|
||||
{
|
||||
QFont f = font();
|
||||
f.setItalic(ital);
|
||||
setFont(f);
|
||||
}
|
||||
|
||||
void TextItem::checkText()
|
||||
{
|
||||
if (document()->textWidth() <= 40)
|
||||
document()->setTextWidth(40);
|
||||
else
|
||||
document()->setTextWidth(-1);
|
||||
|
||||
emit textChanged();
|
||||
}
|
||||
|
||||
void TextItem::setText(const QString &t)
|
||||
{
|
||||
blockSignals(true);
|
||||
setPlainText(t);
|
||||
blockSignals(false);
|
||||
}
|
||||
|
||||
void TextItem::focusInEvent(QFocusEvent *event)
|
||||
{
|
||||
QGraphicsTextItem::focusInEvent(event);
|
||||
emit selected(true);
|
||||
}
|
||||
|
||||
void TextItem::focusOutEvent(QFocusEvent *event)
|
||||
{
|
||||
emit textReady(toPlainText());
|
||||
QGraphicsTextItem::focusOutEvent(event);
|
||||
}
|
||||
|
||||
void TextItem::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Escape:
|
||||
case Qt::Key_Enter:
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Tab:
|
||||
event->accept();
|
||||
clearFocus();
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QGraphicsTextItem::keyPressEvent(event);
|
||||
}
|
||||
|
||||
bool TextItem::needIgnore(const QPointF sPos) const
|
||||
{
|
||||
// If we found QuickTransition-item or CornerGrabber at this point, we must ignore mouse press here
|
||||
// So we can press QuickTransition/CornerGrabber item although there is transition lines front of these items
|
||||
foreach (QGraphicsItem *item, scene()->items(sPos)) {
|
||||
if (item->type() == QuickTransitionType || (item->type() == CornerGrabberType && item->parentItem() != this))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void TextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if (needIgnore(event->scenePos())) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
QGraphicsTextItem::mousePressEvent(event);
|
||||
setFocus();
|
||||
}
|
||||
|
||||
void TextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if (needIgnore(event->scenePos())) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
QGraphicsTextItem::mouseReleaseEvent(event);
|
||||
setFocus();
|
||||
}
|
||||
|
||||
void TextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if (needIgnore(event->scenePos())) {
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
setFocus();
|
||||
QGraphicsTextItem::mouseDoubleClickEvent(event);
|
||||
emit selected(true);
|
||||
}
|
||||
|
||||
void TextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
if (needIgnore(e->scenePos())) {
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
setCursor(Qt::IBeamCursor);
|
||||
QGraphicsTextItem::hoverEnterEvent(e);
|
||||
}
|
||||
|
||||
void TextItem::hoverMoveEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
if (needIgnore(e->scenePos())) {
|
||||
setCursor(Qt::ArrowCursor);
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
setCursor(Qt::IBeamCursor);
|
||||
QGraphicsTextItem::hoverEnterEvent(e);
|
||||
}
|
||||
|
||||
void TextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *e)
|
||||
{
|
||||
setCursor(Qt::ArrowCursor);
|
||||
QGraphicsTextItem::hoverLeaveEvent(e);
|
||||
}
|
||||
76
src/plugins/scxmleditor/plugin_interface/textitem.h
Normal file
76
src/plugins/scxmleditor/plugin_interface/textitem.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
#include <QFocusEvent>
|
||||
#include <QGraphicsTextItem>
|
||||
#include <QKeyEvent>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class TextItem : public QGraphicsTextItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TextItem(QGraphicsItem *parent = nullptr);
|
||||
explicit TextItem(const QString &id, QGraphicsItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return TextType;
|
||||
}
|
||||
|
||||
void setItalic(bool ital);
|
||||
void setText(const QString &t);
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void focusInEvent(QFocusEvent *event) override;
|
||||
void focusOutEvent(QFocusEvent *event) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
signals:
|
||||
void textChanged();
|
||||
void textReady(const QString &text);
|
||||
void selected(bool sel);
|
||||
|
||||
private:
|
||||
void checkText();
|
||||
void init();
|
||||
bool needIgnore(const QPointF sPos) const;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
1276
src/plugins/scxmleditor/plugin_interface/transitionitem.cpp
Normal file
1276
src/plugins/scxmleditor/plugin_interface/transitionitem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
181
src/plugins/scxmleditor/plugin_interface/transitionitem.h
Normal file
181
src/plugins/scxmleditor/plugin_interface/transitionitem.h
Normal file
@@ -0,0 +1,181 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "transitionwarningitem.h"
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsTextItem>
|
||||
#include <QKeyEvent>
|
||||
#include <QPen>
|
||||
#include <QPointF>
|
||||
#include <QPolygon>
|
||||
#include <QRectF>
|
||||
#include <QVector>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class CornerGrabberItem;
|
||||
class TagTextItem;
|
||||
class ConnectableItem;
|
||||
|
||||
/**
|
||||
* @brief The TransitionItem class provides the item to connect two Connectable-items.
|
||||
*/
|
||||
class TransitionItem : public BaseItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TransitionItem(BaseItem *parent = nullptr);
|
||||
~TransitionItem() override;
|
||||
|
||||
enum TransitionTargetType {
|
||||
InternalSameTarget = 0,
|
||||
InternalNoTarget,
|
||||
ExternalNoTarget,
|
||||
ExternalTarget
|
||||
};
|
||||
|
||||
enum TransitionPoint {
|
||||
Start = 0,
|
||||
End
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief type - return tye type of the item.
|
||||
*/
|
||||
int type() const override
|
||||
{
|
||||
return TransitionType;
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
|
||||
|
||||
void disconnectItem(ConnectableItem *item);
|
||||
void setStartItem(ConnectableItem *item);
|
||||
void setEndItem(ConnectableItem *item);
|
||||
|
||||
void startTransitionFrom(ConnectableItem *item, const QPointF &mouseScenePos);
|
||||
void setEndPos(const QPointF &endPos, bool snap = true);
|
||||
void connectToTopItem(const QPointF &pos, TransitionPoint p, ItemType targetType);
|
||||
|
||||
bool isStartItem(const ConnectableItem *item) const;
|
||||
bool isEndItem(const ConnectableItem *item) const;
|
||||
ConnectableItem *connectedItem(const ConnectableItem *other) const;
|
||||
|
||||
bool hasStartItem() const;
|
||||
bool hasEndItem() const;
|
||||
|
||||
void init(ScxmlTag *tag, BaseItem *parentItem = nullptr, bool initChildren = true, bool blockUpdates = false) override;
|
||||
void updateEditorInfo(bool allChilds = true) override;
|
||||
void updateAttributes() override;
|
||||
void updateTarget();
|
||||
void finalizeCreation() override;
|
||||
void checkVisibility(double scaleFactor) override;
|
||||
bool containsScenePoint(const QPointF &p) const override;
|
||||
|
||||
void updateUIProperties() override;
|
||||
void updateTargetType();
|
||||
void setTag(ScxmlTag *tag) override;
|
||||
qreal textWidth() const;
|
||||
QRectF wholeBoundingRect() const;
|
||||
|
||||
TransitionTargetType targetType() const
|
||||
{
|
||||
return m_targetType;
|
||||
}
|
||||
|
||||
void grabMouse(ItemType targetType);
|
||||
void storeGeometry(bool block = false);
|
||||
void storeValues(bool block = false);
|
||||
void updateComponents();
|
||||
void textItemPositionChanged();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void updateToolTip();
|
||||
void readUISpecifiedProperties(const ScxmlTag *tag) override;
|
||||
void checkSelectionBeforeContextMenu(QGraphicsSceneMouseEvent *e) override;
|
||||
void createContextMenu(QMenu *menu) override;
|
||||
void selectedMenuAction(const QAction *action) override;
|
||||
|
||||
private:
|
||||
void textHasChanged(const QString &text);
|
||||
void checkWarningItems();
|
||||
void storeMovePoint(bool block = false);
|
||||
void storeTargetFactors(bool block = false);
|
||||
void updateZValue();
|
||||
void removeUnnecessaryPoints();
|
||||
void findEndItem();
|
||||
void updateEventName();
|
||||
void createGrabbers();
|
||||
void removeGrabbers();
|
||||
void updateGrabberPositions();
|
||||
void removeTransition(TransitionPoint p);
|
||||
void snapToAnyPoint(int index, const QPointF &newPoint, int diff = 8);
|
||||
void snapPointToPoint(int index, const QPointF &newPoint, int diff = 8);
|
||||
QPointF loadPoint(const QString &name);
|
||||
void savePoint(const QPointF &p, const QString &name);
|
||||
QPointF calculateTargetFactor(ConnectableItem *item, const QPointF &pos);
|
||||
QPointF sceneTargetPoint(TransitionPoint p);
|
||||
QPointF findIntersectionPoint(ConnectableItem *item, const QLineF &line, const QPointF &defaultPoint);
|
||||
QVector<CornerGrabberItem*> m_cornerGrabbers;
|
||||
CornerGrabberItem *m_selectedCornerGrabber = nullptr;
|
||||
|
||||
QPolygonF m_cornerPoints;
|
||||
|
||||
ConnectableItem *m_startItem = nullptr;
|
||||
ConnectableItem *m_oldStartItem = nullptr;
|
||||
ConnectableItem *m_endItem = nullptr;
|
||||
|
||||
QPolygonF m_arrow;
|
||||
qreal m_arrowSize = 10;
|
||||
qreal m_arrowAngle;
|
||||
QPen m_pen;
|
||||
QPen m_highlightPen;
|
||||
bool m_lineSelected = false;
|
||||
|
||||
TagTextItem *m_eventTagItem;
|
||||
TransitionWarningItem *m_warningItem = nullptr;
|
||||
TransitionTargetType m_targetType = ExternalTarget;
|
||||
bool m_movingFirstPoint = false;
|
||||
bool m_movingLastPoint = false;
|
||||
bool m_mouseGrabbed = false;
|
||||
ItemType m_grabbedTargetType = UnknownType;
|
||||
int m_selectedGrabberIndex = -1;
|
||||
QPointF m_startTargetFactor;
|
||||
QPointF m_endTargetFactor;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "transitionwarningitem.h"
|
||||
#include "transitionitem.h"
|
||||
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
TransitionWarningItem::TransitionWarningItem(TransitionItem *parent)
|
||||
: WarningItem(parent)
|
||||
, m_parentItem(parent)
|
||||
{
|
||||
setSeverity(OutputPane::Warning::WarningType);
|
||||
setTypeName(tr("Transition"));
|
||||
setDescription(tr("Transitions should be connected."));
|
||||
|
||||
setPixmap(Utils::Icons::WARNING.pixmap());
|
||||
}
|
||||
|
||||
void TransitionWarningItem::check()
|
||||
{
|
||||
if (m_parentItem) {
|
||||
if (m_parentItem->targetType() == TransitionItem::ExternalNoTarget) {
|
||||
setReason(tr("Not Connected (%1)").arg(m_parentItem->tagValue("event")));
|
||||
setWarningActive(true);
|
||||
} else
|
||||
setWarningActive(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "warningitem.h"
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class TransitionItem;
|
||||
|
||||
/**
|
||||
* @brief The TransitionWarningItem class provides the warning item for the check Transition connections.
|
||||
*/
|
||||
class TransitionWarningItem : public WarningItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TransitionWarningItem(TransitionItem *parent = nullptr);
|
||||
|
||||
int type() const override
|
||||
{
|
||||
return TransitionWarningType;
|
||||
}
|
||||
|
||||
void check() override;
|
||||
|
||||
private:
|
||||
TransitionItem *m_parentItem;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
403
src/plugins/scxmleditor/plugin_interface/undocommands.cpp
Normal file
403
src/plugins/scxmleditor/plugin_interface/undocommands.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "undocommands.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
BaseUndoCommand::BaseUndoCommand(ScxmlDocument *doc, QUndoCommand *parent)
|
||||
: QUndoCommand(parent)
|
||||
, m_doc(doc)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseUndoCommand::undo()
|
||||
{
|
||||
m_doc->setUndoRedoRunning(true);
|
||||
doUndo();
|
||||
m_doc->setUndoRedoRunning(false);
|
||||
}
|
||||
|
||||
void BaseUndoCommand::redo()
|
||||
{
|
||||
m_doc->setUndoRedoRunning(!m_firstTime);
|
||||
doRedo();
|
||||
if (m_firstTime)
|
||||
m_firstTime = false;
|
||||
m_doc->setUndoRedoRunning(false);
|
||||
}
|
||||
|
||||
// AddRemoveTagsBeginCommand
|
||||
AddRemoveTagsBeginCommand::AddRemoveTagsBeginCommand(ScxmlDocument *doc, ScxmlTag *tag, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
{
|
||||
}
|
||||
|
||||
void AddRemoveTagsBeginCommand::doUndo()
|
||||
{
|
||||
emit m_document->endTagChange(ScxmlDocument::TagRemoveTags, m_tag, m_tag->index());
|
||||
}
|
||||
void AddRemoveTagsBeginCommand::doRedo()
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagAddTags, m_tag, m_tag->index());
|
||||
}
|
||||
|
||||
// AddRemoveTagsEndCommand
|
||||
AddRemoveTagsEndCommand::AddRemoveTagsEndCommand(ScxmlDocument *doc, ScxmlTag *tag, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
{
|
||||
}
|
||||
|
||||
void AddRemoveTagsEndCommand::doUndo()
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagRemoveTags, m_tag, m_tag->index());
|
||||
}
|
||||
void AddRemoveTagsEndCommand::doRedo()
|
||||
{
|
||||
emit m_document->endTagChange(ScxmlDocument::TagAddTags, m_tag, m_tag->index());
|
||||
}
|
||||
|
||||
// AddRemoveTagCommand
|
||||
AddRemoveTagCommand::AddRemoveTagCommand(ScxmlDocument *doc, ScxmlTag *parentTag, ScxmlTag *tag, ScxmlDocument::TagChange change, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
, m_parentTag(parentTag)
|
||||
, m_change(change)
|
||||
{
|
||||
m_tag->setDocument(m_document);
|
||||
}
|
||||
|
||||
AddRemoveTagCommand::~AddRemoveTagCommand()
|
||||
{
|
||||
// If type was ADD, then delete tag
|
||||
if (m_change == ScxmlDocument::TagAddChild)
|
||||
delete m_tag;
|
||||
}
|
||||
|
||||
void AddRemoveTagCommand::doAction(bool add)
|
||||
{
|
||||
if (add) {
|
||||
int r = m_parentTag->childIndex(m_tag);
|
||||
if (r < 0)
|
||||
r = m_parentTag->childCount();
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagAddChild, m_parentTag, QVariant(r));
|
||||
m_parentTag->appendChild(m_tag);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagAddChild, m_parentTag, QVariant(r));
|
||||
} else {
|
||||
int r = m_parentTag->childIndex(m_tag);
|
||||
if (r >= 0) {
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagRemoveChild, m_parentTag, QVariant(r));
|
||||
m_parentTag->removeChild(m_tag);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagRemoveChild, m_parentTag, QVariant(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddRemoveTagCommand::doUndo()
|
||||
{
|
||||
doAction(m_change != ScxmlDocument::TagAddChild);
|
||||
}
|
||||
void AddRemoveTagCommand::doRedo()
|
||||
{
|
||||
doAction(m_change == ScxmlDocument::TagAddChild);
|
||||
}
|
||||
|
||||
// SetAttributeCommand
|
||||
SetAttributeCommand::SetAttributeCommand(ScxmlDocument *doc, ScxmlTag *tag, const QString &key, const QString &value, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
, m_key(key)
|
||||
, m_value(value)
|
||||
{
|
||||
m_oldValue = m_tag->attribute(m_key);
|
||||
}
|
||||
|
||||
void SetAttributeCommand::doAction(const QString &key, const QString &value)
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagAttributesChanged, m_tag, m_tag->attribute(key));
|
||||
m_tag->setAttribute(key, value);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagAttributesChanged, m_tag, value);
|
||||
}
|
||||
|
||||
int SetAttributeCommand::id() const
|
||||
{
|
||||
return (int)ScxmlDocument::TagAttributesChanged;
|
||||
}
|
||||
bool SetAttributeCommand::mergeWith(const QUndoCommand *other)
|
||||
{
|
||||
if (other->id() == id()) {
|
||||
QString key = static_cast<const SetAttributeCommand*>(other)->m_key;
|
||||
auto tag = static_cast<const SetAttributeCommand*>(other)->m_tag;
|
||||
if (tag == m_tag && key == m_key) {
|
||||
m_value = static_cast<const SetAttributeCommand*>(other)->m_value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetAttributeCommand::doUndo()
|
||||
{
|
||||
doAction(m_key, m_oldValue);
|
||||
}
|
||||
void SetAttributeCommand::doRedo()
|
||||
{
|
||||
doAction(m_key, m_value);
|
||||
}
|
||||
|
||||
// SetContentCommand
|
||||
SetContentCommand::SetContentCommand(ScxmlDocument *doc, ScxmlTag *tag, const QString &content, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
, m_content(content)
|
||||
{
|
||||
m_oldContent = m_tag->content();
|
||||
}
|
||||
|
||||
void SetContentCommand::doAction(const QString &content)
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagContentChanged, m_tag, m_tag->content());
|
||||
m_tag->setContent(content);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagContentChanged, m_tag, content);
|
||||
}
|
||||
|
||||
int SetContentCommand::id() const
|
||||
{
|
||||
return (int)ScxmlDocument::TagContentChanged;
|
||||
}
|
||||
bool SetContentCommand::mergeWith(const QUndoCommand *other)
|
||||
{
|
||||
if (other->id() == id()) {
|
||||
auto tag = static_cast<const SetContentCommand*>(other)->m_tag;
|
||||
if (tag == m_tag) {
|
||||
m_content = static_cast<const SetContentCommand*>(other)->m_content;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetContentCommand::doUndo()
|
||||
{
|
||||
doAction(m_oldContent);
|
||||
}
|
||||
void SetContentCommand::doRedo()
|
||||
{
|
||||
doAction(m_content);
|
||||
}
|
||||
|
||||
// SetEditorInfoCommand
|
||||
SetEditorInfoCommand::SetEditorInfoCommand(ScxmlDocument *doc, ScxmlTag *tag, const QString &key, const QString &value, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
, m_key(key)
|
||||
, m_value(value)
|
||||
{
|
||||
m_oldValue = m_tag->editorInfo(m_key);
|
||||
}
|
||||
|
||||
void SetEditorInfoCommand::doAction(const QString &key, const QString &value)
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagEditorInfoChanged, m_tag, m_tag->editorInfo(key));
|
||||
m_tag->setEditorInfo(key, value);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagEditorInfoChanged, m_tag, value);
|
||||
}
|
||||
|
||||
int SetEditorInfoCommand::id() const
|
||||
{
|
||||
return (int)ScxmlDocument::TagEditorInfoChanged;
|
||||
}
|
||||
bool SetEditorInfoCommand::mergeWith(const QUndoCommand *other)
|
||||
{
|
||||
if (other->id() == id()) {
|
||||
QString key = static_cast<const SetEditorInfoCommand*>(other)->m_key;
|
||||
auto tag = static_cast<const SetEditorInfoCommand*>(other)->m_tag;
|
||||
if (tag == m_tag && key == m_key) {
|
||||
m_value = static_cast<const SetEditorInfoCommand*>(other)->m_value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetEditorInfoCommand::doUndo()
|
||||
{
|
||||
doAction(m_key, m_oldValue);
|
||||
}
|
||||
void SetEditorInfoCommand::doRedo()
|
||||
{
|
||||
doAction(m_key, m_value);
|
||||
}
|
||||
|
||||
// ChangeParentCommand
|
||||
ChangeParentCommand::ChangeParentCommand(ScxmlDocument *doc, ScxmlTag *tag, ScxmlTag *newParentTag, int tagIndex, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
, m_newParentTag(newParentTag)
|
||||
, m_tagIndex(tagIndex)
|
||||
{
|
||||
m_oldParentTag = m_tag->parentTag();
|
||||
}
|
||||
|
||||
void ChangeParentCommand::doAction(ScxmlTag *oldParent, ScxmlTag *newParent)
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagChangeParent, m_tag, m_tag->index());
|
||||
|
||||
int r = oldParent->childIndex(m_tag);
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagChangeParentRemoveChild, oldParent, QVariant(r));
|
||||
oldParent->removeChild(m_tag);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagChangeParentRemoveChild, oldParent, QVariant(r));
|
||||
|
||||
r = newParent->childCount();
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagChangeParentAddChild, newParent, QVariant(r));
|
||||
newParent->insertChild(m_tagIndex, m_tag);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagChangeParentAddChild, newParent, QVariant(r));
|
||||
|
||||
emit m_document->endTagChange(ScxmlDocument::TagChangeParent, m_tag, m_tag->index());
|
||||
}
|
||||
|
||||
void ChangeParentCommand::doUndo()
|
||||
{
|
||||
doAction(m_newParentTag, m_oldParentTag);
|
||||
}
|
||||
void ChangeParentCommand::doRedo()
|
||||
{
|
||||
doAction(m_oldParentTag, m_newParentTag);
|
||||
}
|
||||
|
||||
ChangeOrderCommand::ChangeOrderCommand(ScxmlDocument *doc, ScxmlTag *tag, ScxmlTag *parentTag, int newPos, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_tag(tag)
|
||||
, m_parentTag(parentTag)
|
||||
, m_newPos(newPos)
|
||||
{
|
||||
m_oldPos = m_tag->index();
|
||||
}
|
||||
|
||||
void ChangeOrderCommand::doAction(int newPos)
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagChangeOrder, m_tag, newPos);
|
||||
m_parentTag->moveChild(m_tag->index(), newPos);
|
||||
emit m_document->endTagChange(ScxmlDocument::TagChangeOrder, m_tag, m_tag->index());
|
||||
}
|
||||
|
||||
void ChangeOrderCommand::doUndo()
|
||||
{
|
||||
doAction(m_oldPos);
|
||||
}
|
||||
void ChangeOrderCommand::doRedo()
|
||||
{
|
||||
doAction(m_newPos);
|
||||
}
|
||||
|
||||
ChangeFullNameSpaceCommand::ChangeFullNameSpaceCommand(ScxmlDocument *doc, ScxmlTag *tag, bool state, QUndoCommand *parent)
|
||||
: BaseUndoCommand(doc, parent)
|
||||
, m_document(doc)
|
||||
, m_rootTag(tag)
|
||||
, m_newState(state)
|
||||
{
|
||||
m_oldState = !state;
|
||||
}
|
||||
|
||||
void ChangeFullNameSpaceCommand::makeIdMap(ScxmlTag *tag, QHash<QString, QString> &map, bool use)
|
||||
{
|
||||
switch (tag->tagType()) {
|
||||
case History:
|
||||
case Final:
|
||||
case State:
|
||||
case Parallel: {
|
||||
QString strId = tag->attribute("id");
|
||||
QString strIdWithNS = QString::fromLatin1("%1%2").arg(tag->stateNameSpace()).arg(strId);
|
||||
map[use ? strId : strIdWithNS] = use ? strIdWithNS : strId;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (ScxmlTag *child, tag->allChildren()) {
|
||||
makeIdMap(child, map, use);
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeFullNameSpaceCommand::updateNameSpace(ScxmlTag *tag, const QHash<QString, QString> &map)
|
||||
{
|
||||
QString name;
|
||||
switch (tag->tagType()) {
|
||||
case Scxml:
|
||||
case State:
|
||||
name = "initial";
|
||||
break;
|
||||
case Transition:
|
||||
name = "target";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!name.isEmpty()) {
|
||||
QString attr = tag->attribute(name);
|
||||
if (map.contains(attr))
|
||||
tag->setAttribute(name, map[attr]);
|
||||
}
|
||||
|
||||
foreach (ScxmlTag *child, tag->allChildren()) {
|
||||
updateNameSpace(child, map);
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeFullNameSpaceCommand::doAction(bool newState)
|
||||
{
|
||||
emit m_document->beginTagChange(ScxmlDocument::TagChangeFullNameSpace, m_rootTag, newState);
|
||||
|
||||
QHash<QString, QString> keyMap;
|
||||
makeIdMap(m_rootTag, keyMap, newState);
|
||||
updateNameSpace(m_rootTag, keyMap);
|
||||
m_document->m_useFullNameSpace = newState;
|
||||
|
||||
emit m_document->endTagChange(ScxmlDocument::TagChangeFullNameSpace, m_rootTag, newState);
|
||||
}
|
||||
|
||||
void ChangeFullNameSpaceCommand::doUndo()
|
||||
{
|
||||
doAction(m_oldState);
|
||||
}
|
||||
void ChangeFullNameSpaceCommand::doRedo()
|
||||
{
|
||||
doAction(m_newState);
|
||||
}
|
||||
232
src/plugins/scxmleditor/plugin_interface/undocommands.h
Normal file
232
src/plugins/scxmleditor/plugin_interface/undocommands.h
Normal file
@@ -0,0 +1,232 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scxmldocument.h"
|
||||
#include "scxmltag.h"
|
||||
#include <QUndoCommand>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class BaseUndoCommand : public QUndoCommand
|
||||
{
|
||||
public:
|
||||
BaseUndoCommand(ScxmlDocument *doc, QUndoCommand *parent = nullptr);
|
||||
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
protected:
|
||||
virtual void doUndo() = 0;
|
||||
virtual void doRedo() = 0;
|
||||
|
||||
private:
|
||||
ScxmlDocument *m_doc;
|
||||
bool m_firstTime = true;
|
||||
};
|
||||
|
||||
class AddRemoveTagsBeginCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
AddRemoveTagsBeginCommand(ScxmlDocument *doc, ScxmlTag *tag, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
private:
|
||||
ScxmlDocument *m_document;
|
||||
ScxmlTag *m_tag;
|
||||
};
|
||||
|
||||
class AddRemoveTagsEndCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
AddRemoveTagsEndCommand(ScxmlDocument *doc, ScxmlTag *tag, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
private:
|
||||
ScxmlDocument *m_document;
|
||||
ScxmlTag *m_tag;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The AddRemoveTagCommand class provides the undo-command to add/remove tag to/from SCXML-document.
|
||||
*/
|
||||
class AddRemoveTagCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
AddRemoveTagCommand(ScxmlDocument *doc, ScxmlTag *parentTag, ScxmlTag *tag, ScxmlDocument::TagChange change, QUndoCommand *parent = nullptr);
|
||||
~AddRemoveTagCommand() override;
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
private:
|
||||
void doAction(bool add);
|
||||
ScxmlDocument *m_document;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
QPointer<ScxmlTag> m_parentTag;
|
||||
ScxmlDocument::TagChange m_change;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The SetAttributeCommand class provides the undo-command to set attribute-value for the given ScxmlTag.
|
||||
*/
|
||||
class SetAttributeCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
SetAttributeCommand(ScxmlDocument *doc, ScxmlTag *tag, const QString &key, const QString &value, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
bool mergeWith(const QUndoCommand *other) override;
|
||||
int id() const override;
|
||||
|
||||
private:
|
||||
void doAction(const QString &key, const QString &value);
|
||||
ScxmlDocument *m_document;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
QString m_key;
|
||||
QString m_value;
|
||||
QString m_oldValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The SetContentCommand class
|
||||
*/
|
||||
class SetContentCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
SetContentCommand(ScxmlDocument *doc, ScxmlTag *tag, const QString &content, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
bool mergeWith(const QUndoCommand *other) override;
|
||||
int id() const override;
|
||||
|
||||
private:
|
||||
void doAction(const QString &content);
|
||||
ScxmlDocument *m_document;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
QString m_content;
|
||||
QString m_oldContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The SetEditorInfoCommand class provides the undo-command to set editorinfo-value for the given ScxmlTag.
|
||||
*/
|
||||
class SetEditorInfoCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
SetEditorInfoCommand(ScxmlDocument *doc, ScxmlTag *tag, const QString &key, const QString &value, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
bool mergeWith(const QUndoCommand *other) override;
|
||||
int id() const override;
|
||||
|
||||
private:
|
||||
void doAction(const QString &key, const QString &value);
|
||||
ScxmlDocument *m_document;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
QString m_key;
|
||||
QString m_value;
|
||||
QString m_oldValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ChangeParentCommand class provides the undo-commant to change parent of the ScxmlTag.
|
||||
*/
|
||||
class ChangeParentCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
ChangeParentCommand(ScxmlDocument *doc, ScxmlTag *tag, ScxmlTag *newParentTag, int tagIndex, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
private:
|
||||
void doAction(ScxmlTag *oldParent, ScxmlTag *newParent);
|
||||
|
||||
ScxmlDocument *m_document;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
QPointer<ScxmlTag> m_newParentTag;
|
||||
QPointer<ScxmlTag> m_oldParentTag;
|
||||
int m_tagIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ChangeOrderCommand class
|
||||
*/
|
||||
class ChangeOrderCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
ChangeOrderCommand(ScxmlDocument *doc, ScxmlTag *tag, ScxmlTag *parentTag, int newPos, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
private:
|
||||
void doAction(int newPos);
|
||||
|
||||
ScxmlDocument *m_document;
|
||||
QPointer<ScxmlTag> m_tag;
|
||||
QPointer<ScxmlTag> m_parentTag;
|
||||
int m_oldPos;
|
||||
int m_newPos;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ChangeNameSpaceCommand class
|
||||
*/
|
||||
class ChangeFullNameSpaceCommand : public BaseUndoCommand
|
||||
{
|
||||
public:
|
||||
ChangeFullNameSpaceCommand(ScxmlDocument *doc, ScxmlTag *tag, bool state, QUndoCommand *parent = nullptr);
|
||||
|
||||
void doUndo() override;
|
||||
void doRedo() override;
|
||||
|
||||
private:
|
||||
void doAction(bool state);
|
||||
void makeIdMap(ScxmlTag *tag, QHash<QString, QString> &map, bool use);
|
||||
void updateNameSpace(ScxmlTag *tag, const QHash<QString, QString> &map);
|
||||
|
||||
ScxmlDocument *m_document;
|
||||
QPointer<ScxmlTag> m_rootTag;
|
||||
bool m_oldState;
|
||||
bool m_newState;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
33
src/plugins/scxmleditor/plugin_interface/utilsprovider.cpp
Normal file
33
src/plugins/scxmleditor/plugin_interface/utilsprovider.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "utilsprovider.h"
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
UtilsProvider::UtilsProvider(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
49
src/plugins/scxmleditor/plugin_interface/utilsprovider.h
Normal file
49
src/plugins/scxmleditor/plugin_interface/utilsprovider.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlTag;
|
||||
|
||||
class UtilsProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UtilsProvider(QObject *parent = nullptr);
|
||||
|
||||
virtual void checkInitialState(const QList<QGraphicsItem*> &items, ScxmlTag *tag) = 0;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
171
src/plugins/scxmleditor/plugin_interface/warningitem.cpp
Normal file
171
src/plugins/scxmleditor/plugin_interface/warningitem.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "warningitem.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "warningmodel.h"
|
||||
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QToolTip>
|
||||
|
||||
using namespace ScxmlEditor::PluginInterface;
|
||||
|
||||
WarningItem::WarningItem(QGraphicsItem *parent)
|
||||
: QGraphicsObject(parent)
|
||||
, m_parentItem(qgraphicsitem_cast<BaseItem*>(parent))
|
||||
{
|
||||
setPixmap(Utils::Icons::WARNING.pixmap());
|
||||
|
||||
auto sc = static_cast<GraphicsScene*>(scene());
|
||||
if (sc) {
|
||||
sc->addWarningItem(this);
|
||||
m_warningModel = sc->warningModel();
|
||||
connect(m_warningModel, &OutputPane::WarningModel::modelCleared, this, &WarningItem::check);
|
||||
}
|
||||
setWarningActive(false);
|
||||
}
|
||||
|
||||
WarningItem::~WarningItem()
|
||||
{
|
||||
auto sc = static_cast<GraphicsScene*>(scene());
|
||||
if (sc) {
|
||||
sc->removeWarningItem(this);
|
||||
delete m_warning;
|
||||
m_warning = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WarningItem::check()
|
||||
{
|
||||
}
|
||||
|
||||
QRectF WarningItem::boundingRect() const
|
||||
{
|
||||
return QRectF(QPointF(), m_pixmap.size() * m_pixmap.devicePixelRatio());
|
||||
}
|
||||
|
||||
void WarningItem::mousePressEvent(QGraphicsSceneMouseEvent *e)
|
||||
{
|
||||
QToolTip::showText(e->screenPos(), toolTip(), 0);
|
||||
QGraphicsObject::mousePressEvent(e);
|
||||
}
|
||||
|
||||
QVariant WarningItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
switch (change) {
|
||||
case ItemSceneHasChanged: {
|
||||
auto sc = static_cast<GraphicsScene*>(scene());
|
||||
if (sc) {
|
||||
sc->addWarningItem(this);
|
||||
m_warningModel = sc->warningModel();
|
||||
connect(m_warningModel, &OutputPane::WarningModel::modelCleared, this, &WarningItem::check);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QGraphicsItem::ItemVisibleHasChanged: {
|
||||
auto sc = static_cast<GraphicsScene*>(scene());
|
||||
if (sc)
|
||||
sc->warningVisibilityChanged(m_severity, this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QGraphicsObject::itemChange(change, value);
|
||||
}
|
||||
|
||||
void WarningItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(widget)
|
||||
|
||||
painter->drawPixmap(0, 0, m_pixmap);
|
||||
}
|
||||
|
||||
void WarningItem::setReason(const QString &reason)
|
||||
{
|
||||
m_reason = reason;
|
||||
if (m_warning)
|
||||
m_warning->setReason(reason);
|
||||
|
||||
setToolTip(m_reason);
|
||||
}
|
||||
|
||||
void WarningItem::setDescription(const QString &description)
|
||||
{
|
||||
m_description = description;
|
||||
if (m_warning)
|
||||
m_warning->setDescription(description);
|
||||
}
|
||||
|
||||
void WarningItem::setSeverity(ScxmlEditor::OutputPane::Warning::Severity type)
|
||||
{
|
||||
m_severity = type;
|
||||
if (m_warning)
|
||||
m_warning->setSeverity(type);
|
||||
}
|
||||
|
||||
void WarningItem::setTypeName(const QString &name)
|
||||
{
|
||||
m_typeName = name;
|
||||
if (m_warning)
|
||||
m_warning->setTypeName(name);
|
||||
}
|
||||
|
||||
void WarningItem::setWarningActive(bool active)
|
||||
{
|
||||
if (active && m_warning == nullptr && m_warningModel) {
|
||||
m_warning = m_warningModel->createWarning(m_severity, m_typeName, m_reason, m_description);
|
||||
connect(m_warning, &OutputPane::Warning::dataChanged, this, &WarningItem::checkVisibility);
|
||||
} else if (!active && m_warning) {
|
||||
m_warning->deleteLater();
|
||||
m_warning = nullptr;
|
||||
}
|
||||
|
||||
checkVisibility();
|
||||
}
|
||||
|
||||
void WarningItem::checkVisibility()
|
||||
{
|
||||
setVisible(m_warning && m_warning->isActive());
|
||||
}
|
||||
|
||||
void WarningItem::setPixmap(const QPixmap &pixmap)
|
||||
{
|
||||
m_pixmap = pixmap.scaled(QSize(25, 25) * pixmap.devicePixelRatio());
|
||||
}
|
||||
|
||||
ScxmlTag *WarningItem::tag() const
|
||||
{
|
||||
return m_parentItem ? m_parentItem->tag() : 0;
|
||||
}
|
||||
|
||||
ScxmlEditor::OutputPane::Warning *WarningItem::warning() const
|
||||
{
|
||||
return m_warning;
|
||||
}
|
||||
85
src/plugins/scxmleditor/plugin_interface/warningitem.h
Normal file
85
src/plugins/scxmleditor/plugin_interface/warningitem.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "baseitem.h"
|
||||
#include "warning.h"
|
||||
#include "warningmodel.h"
|
||||
#include <QGraphicsObject>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPixmap>
|
||||
#include <QPointer>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
/**
|
||||
* @brief The WarningItem class is a base class for the all scene-based Warning-items.
|
||||
*
|
||||
* When status changes, warning must inform it to scene. Scene will check the other warnings too.
|
||||
*/
|
||||
class WarningItem : public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WarningItem(QGraphicsItem *parent = nullptr);
|
||||
~WarningItem() override;
|
||||
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
QRectF boundingRect() const override;
|
||||
ScxmlTag *tag() const;
|
||||
|
||||
void setSeverity(OutputPane::Warning::Severity type);
|
||||
void setTypeName(const QString &name);
|
||||
void setDescription(const QString &description);
|
||||
OutputPane::Warning *warning() const;
|
||||
|
||||
void setReason(const QString &reason);
|
||||
void setPixmap(const QPixmap &pixmap);
|
||||
void setWarningActive(bool active);
|
||||
virtual void check();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
void checkVisibility();
|
||||
|
||||
OutputPane::Warning::Severity m_severity = OutputPane::Warning::ErrorType;
|
||||
QString m_typeName;
|
||||
QString m_description;
|
||||
QString m_reason;
|
||||
QPixmap m_pixmap;
|
||||
BaseItem *m_parentItem;
|
||||
QPointer<OutputPane::Warning> m_warning;
|
||||
QPointer<OutputPane::WarningModel> m_warningModel;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
54
src/plugins/scxmleditor/plugin_interface/warningprovider.h
Normal file
54
src/plugins/scxmleditor/plugin_interface/warningprovider.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace ScxmlEditor {
|
||||
|
||||
namespace OutputPane {
|
||||
class WarningModel;
|
||||
} // namespace OutputPane
|
||||
|
||||
namespace PluginInterface {
|
||||
|
||||
class ScxmlTag;
|
||||
|
||||
class WarningProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WarningProvider(QObject *parent = nullptr)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void init(OutputPane::WarningModel *model) = 0;
|
||||
};
|
||||
|
||||
} // namespace PluginInterface
|
||||
} // namespace ScxmlEditor
|
||||
Reference in New Issue
Block a user