Commit a2e6b8c0 authored by Ralf Habacker's avatar Ralf Habacker
Browse files

Add support for linking a state diagram to classes

In classifier context menu entries for "Remove state diagram"
and "goto state diagram" has been added.

Related menu selection code has been added to
DiagramProxyWidget::slotMenuSelection().

BUG:413579
FIXED-IN:2.30.80 (KDE Applications 20.03.80)
parent ecec7d07
......@@ -195,6 +195,7 @@ void ListPopupMenu::insert(const MenuType m, KMenu* menu)
case mt_FloatText: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Text), i18n("Text Line...")); break;
case mt_ForeignKeyConstraint: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Constraint_ForeignKey), i18n("Foreign Key Constraint...")); break;
case mt_Fork: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Fork_Join), i18n("Fork")); break;
case mt_GoToStateDiagram: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Remove), i18n("Go to state diagram")); break;
case mt_Import_Class: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Import_File), i18n("Import File(s)...")); break;
case mt_Import_Project: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Import_Project), i18n("Import from Directory...")); break;
case mt_Import_from_File: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Import_File), i18n("from file...")); break;
......@@ -242,9 +243,11 @@ void ListPopupMenu::insert(const MenuType m, KMenu* menu)
case mt_Redo: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Redo), i18n("Redo")); break;
case mt_Region: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Region), i18n("Region")); break;
case mt_Remove: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Remove), i18n("Remove")); break;
case mt_RemoveStateDiagram: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Remove), i18n("Remove state diagram")); break;
case mt_Rename: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Rename), i18n("Rename...")); break;
case mt_Rename_Object: insert(m, menu, i18n("Rename Object...")); break;
case mt_ReturnToCombinedState: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Redo), i18n("Return to combined state")); break;
case mt_ReturnToClass: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Redo), i18n("Return to class")); break;
case mt_Reset_Label_Positions: m_actions[m] = menu->addAction(i18n("Reset Label Positions")); break;
case mt_Resize: insert(m, menu, i18n("Resize")); break;
case mt_Send_Signal: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Send_Signal), i18n("Send Signal")); break;
......@@ -254,6 +257,7 @@ void ListPopupMenu::insert(const MenuType m, KMenu* menu)
case mt_StateFork: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Fork_State), i18n("Fork")); break;
case mt_StateJoin: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Join), i18n("Join")); break;
case mt_StateTransition: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_State_Transition), i18n("State Transition")); break;
case mt_State_Diagram: insertFromActionKey(m, menu, QLatin1String("new_state_diagram")); break;
case mt_Subsystem: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Subsystem), i18n("Subsystem")); break;
//case mt_Subsystem: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Subsystem), i18n("Subsystem...")); break;
case mt_Template: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Template_Class), i18n("Template")); break;
......
......@@ -88,6 +88,7 @@ public:
mt_Final_Activity,
mt_ForeignKeyConstraint,
mt_Fork,
mt_GoToStateDiagram,
mt_Initial_Activity,
mt_Initial_State,
mt_Invoke_Activity,
......@@ -135,6 +136,8 @@ public:
mt_New_Operation,
mt_New_Parameter,
mt_New_Template,
mt_RemoveStateDiagram,
mt_ReturnToClass,
mt_ReturnToCombinedState,
// selection
// visual properties
......
......@@ -37,8 +37,12 @@ UMLScenePopupMenu::UMLScenePopupMenu(QWidget *parent, UMLScene *scene)
case Uml::DiagramType::EntityRelationship:
case Uml::DiagramType::Sequence:
case Uml::DiagramType::Collaboration:
if (type == Uml::DiagramType::State && scene->widgetLink())
insert(mt_ReturnToCombinedState);
if (type == Uml::DiagramType::State && scene->widgetLink()) {
if (scene->widgetLink()->isStateWidget())
insert(mt_ReturnToCombinedState);
else if (scene->widgetLink()->isClassWidget())
insert(mt_ReturnToClass);
}
insertSubMenuNew(type);
addSeparator();
insert(mt_Undo);
......
......@@ -190,6 +190,11 @@ void WidgetBasePopupMenu::insertSingleSelectionMenu(WidgetBase* widget)
insertSubMenuNew(type);
makeClassifierShowPopup(c);
insertSubMenuColor(c->useFillColor());
if (c->linkedDiagram()) {
addSeparator();
insert(mt_GoToStateDiagram);
insert(mt_RemoveStateDiagram);
}
insertStdItems(true, type);
insert(mt_Rename);
insert(mt_Change_Font);
......@@ -661,6 +666,7 @@ void WidgetBasePopupMenu::insertSubMenuNew(WidgetBase::WidgetType type, KMenu *m
insert(mt_Interface, menu);
insert(mt_Datatype, menu);
insert(mt_Enum, menu);
insert(mt_State_Diagram, menu);
break;
case WidgetBase::wt_Interface:
insert(mt_Operation, menu);
......
......@@ -3207,6 +3207,7 @@ void UMLScene::slotMenuSelection(QAction* action)
}
break;
case ListPopupMenu::mt_ReturnToClass:
case ListPopupMenu::mt_ReturnToCombinedState:
if (widgetLink()) {
UMLApp::app()->document()->changeCurrentView(widgetLink()->umlScene()->ID());
......
......@@ -18,6 +18,8 @@
#include "classifier.h"
#include "cmds.h"
#include "debug_utils.h"
#include "diagram_utils.h"
#include "dialog_utils.h"
#include "instance.h"
#include "listpopupmenu.h"
#include "object_factory.h"
......@@ -26,6 +28,7 @@
#include "uml.h"
#include "umldoc.h"
#include "umlview.h"
#include "widget_utils.h"
// qt includes
#include <QPainter>
......@@ -46,6 +49,7 @@ ClassifierWidget::ClassifierWidget(UMLScene * scene, UMLClassifier *c)
m_pAssocWidget(nullptr),
m_pInterfaceName(nullptr)
{
DiagramProxyWidget::setShowLinkedDiagram(false);
const Settings::OptionState& ops = m_scene->optionState();
setVisualPropertyCmd(ShowVisibility, ops.classState.showVisibility);
setVisualPropertyCmd(ShowOperations, ops.classState.showOps);
......@@ -613,6 +617,9 @@ QSizeF ClassifierWidget::calculateSize(bool withExtensions /* = true */) const
// allow for width margin
width += defaultMargin * 2;
if (DiagramProxyWidget::linkedDiagram() || DiagramProxyWidget::diagramLink() != Uml::ID::None)
width += 2 * DiagramProxyWidget::iconRect().width();
return QSizeF(width, height);
}
......@@ -873,6 +880,10 @@ void ClassifierWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *
}
}
if (DiagramProxyWidget::linkedDiagram()) {
DiagramProxyWidget::paint(painter, option, widget);
}
UMLWidget::paint(painter, option, widget);
}
......@@ -1254,6 +1265,9 @@ bool ClassifierWidget::loadFromXMI1(QDomElement & qElement)
if (!UMLWidget::loadFromXMI1(qElement)) {
return false;
}
if (DiagramProxyWidget::linkedDiagram())
DiagramProxyWidget::setShowLinkedDiagram(false);
bool loadShowAttributes = true;
if (umlObject() && (umlObject()->isUMLPackage() || umlObject()->isUMLInstance())) {
loadShowAttributes = false;
......@@ -1459,7 +1473,7 @@ void ClassifierWidget::slotMenuSelection(QAction* action)
break;
default:
UMLWidget::slotMenuSelection(action);
DiagramProxyWidget::slotMenuSelection(action);
break;
}
}
......@@ -1480,6 +1494,14 @@ void ClassifierWidget::slotShowOperations(bool state)
setVisualProperty(ShowOperations, state);
}
void ClassifierWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (linkedDiagram())
DiagramProxyWidget::mouseDoubleClickEvent(event);
if (event->isAccepted())
UMLWidget::mouseDoubleClickEvent(event);
}
/**
* Show a properties dialog for a ClassifierWidget
*/
......
......@@ -115,6 +115,9 @@ private Q_SLOTS:
void slotShowAttributes(bool state);
void slotShowOperations(bool state);
protected:
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
private:
void updateSignatureTypes();
QSize calculateTemplatesBoxSize() const;
......
......@@ -10,7 +10,13 @@
#include "diagramproxywidget.h"
#include "cmds/cmdcreatediagram.h"
#include "debug_utils.h"
#include "diagram_utils.h"
#include "dialog_utils.h"
#include "widget_utils.h"
#include "listpopupmenu.h"
#include "statewidget.h"
#include "uml.h"
#include "umldoc.h"
#include "umlscene.h"
......@@ -21,27 +27,36 @@ DEBUG_REGISTER_DISABLED(DiagramProxyWidget)
DiagramProxyWidget::DiagramProxyWidget(UMLWidget *widget, qreal borderWidth)
: m_diagramLinkId(Uml::ID::None)
, m_iconRect(QRectF(0, 0, 10, 10))
, m_widget(widget)
, m_borderWidth(borderWidth)
, m_showLinkedDiagram(true)
{
}
Uml::ID::Type DiagramProxyWidget::diagramLink()
Uml::ID::Type DiagramProxyWidget::diagramLink() const
{
return m_diagramLinkId;
}
UMLScene *DiagramProxyWidget::linkedDiagram()
UMLScene *DiagramProxyWidget::linkedDiagram() const
{
return m_linkedDiagram;
}
bool DiagramProxyWidget::setDiagramLink(const Uml::ID::Type &id)
{
if (id == Uml::ID::None) {
m_diagramLinkId = id;
m_linkedDiagram = nullptr;
m_widget->updateGeometry(true);
return true;
}
UMLView *view = UMLApp::app()->document()->findView(id);
if (view) {
m_diagramLinkId = id;
m_linkedDiagram = view->umlScene();
m_widget->updateGeometry(true);
}
return view;
}
......@@ -210,13 +225,22 @@ void DiagramProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
void DiagramProxyWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
QPointF pos = m_widget->mapFromScene(event->scenePos());
if (m_linkedDiagram && m_clientRect.contains(pos)) {
QGraphicsSceneMouseEvent e(event->type());
setupEvent(e, event, pos);
m_linkedDiagram->mouseDoubleClickEvent(&e);
m_widget->update();
event->ignore();
if (m_showLinkedDiagram) {
QPointF pos = m_widget->mapFromScene(event->scenePos());
if (m_linkedDiagram && m_clientRect.contains(pos)) {
QGraphicsSceneMouseEvent e(event->type());
setupEvent(e, event, pos);
m_linkedDiagram->mouseDoubleClickEvent(&e);
m_widget->update();
event->ignore();
}
} else {
QPointF p = m_widget->mapFromScene(event->scenePos());
if (m_iconRect.contains(p)) {
linkedDiagram()->setWidgetLink(dynamic_cast<WidgetBase *>(this));
UMLApp::app()->document()->changeCurrentView(diagramLink());
event->ignore();
}
}
}
......@@ -256,6 +280,42 @@ void DiagramProxyWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
}
/**
* Getter for icon rectangle
* @return icon rectangle
*/
QRectF DiagramProxyWidget::iconRect() const
{
return m_iconRect;
}
/**
* Setter for icon rectangle
* @param iconRect icon rectangle
*/
void DiagramProxyWidget::setIconRect(const QRectF &iconRect)
{
m_iconRect = iconRect;
}
/**
* Return state of 'show linked diagram' attribute
* @return state
*/
bool DiagramProxyWidget::showLinkedDiagram() const
{
return m_showLinkedDiagram;
}
/**
* Set state for 'show linked diagram' attribute
* @param showLinkedDiagram state to set
*/
void DiagramProxyWidget::setShowLinkedDiagram(bool showLinkedDiagram)
{
m_showLinkedDiagram = showLinkedDiagram;
}
/**
* Paint linked diagram into current widget
*
......@@ -268,10 +328,65 @@ void DiagramProxyWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem
Q_UNUSED(option);
Q_UNUSED(widget);
m_sceneRect = linkedDiagram()->sceneRect().adjusted(-1,-1, 1, 1);
if (Tracer::instance()->isEnabled(QLatin1String("DiagramProxyWidget"))) {
painter->setPen(Qt::magenta);
painter->drawRect(m_clientRect);
if (m_showLinkedDiagram) {
m_sceneRect = linkedDiagram()->sceneRect().adjusted(-1,-1, 1, 1);
if (Tracer::instance()->isEnabled(QLatin1String("DiagramProxyWidget"))) {
painter->setPen(Qt::magenta);
painter->drawRect(m_clientRect);
}
m_linkedDiagram->render(painter, m_clientRect, m_sceneRect);
} else {
QPixmap p = Icon_Utils::smallIcon(Uml::DiagramType::State);
QRectF source(0,0, p.width(), p.height());
painter->drawPixmap(m_iconRect, p, source);
}
}
/**
* Captures any popup menu signals for menus it created.
*
* If the provided action is not handled, it will be forwarded
* to the contained widget.
*
* @param action action to handle
*/
void DiagramProxyWidget::slotMenuSelection(QAction* action)
{
switch(ListPopupMenu::typeFromAction(action)) {
case ListPopupMenu::mt_State_Diagram:
{
QString name = Widget_Utils::defaultWidgetName(WidgetBase::WidgetType::wt_State);
bool ok;
do {
if (!Diagram_Utils::isUniqueDiagramName(Uml::DiagramType::State, name))
name.append(QLatin1String("_1"));
ok = Dialog_Utils::askNewName(WidgetBase::WidgetType::wt_State, name);
} while(ok && !Diagram_Utils::isUniqueDiagramName(Uml::DiagramType::State, name));
if (ok) {
Uml::CmdCreateDiagram* d = new Uml::CmdCreateDiagram(UMLApp::app()->document(), Uml::DiagramType::State, name);
UMLApp::app()->executeCommand(d);
setShowLinkedDiagram(false);
setDiagramLink(d->view()->umlScene()->ID());
d->view()->umlScene()->setWidgetLink(m_widget);
}
}
break;
case ListPopupMenu::mt_GoToStateDiagram:
if (!linkedDiagram()) {
uError() << "no diagram id defined at widget '" << Uml::ID::toString(m_widget->id()) << "'";
break;
}
linkedDiagram()->setWidgetLink(m_widget);
UMLApp::app()->document()->changeCurrentView(diagramLink());
break;
case ListPopupMenu::mt_RemoveStateDiagram:
setDiagramLink(Uml::ID::None);
break;
default:
m_widget->UMLWidget::slotMenuSelection(action);
break;
}
m_linkedDiagram->render(painter, m_clientRect, m_sceneRect);
}
......@@ -21,6 +21,7 @@
class UMLWidget;
class UMLScene;
class IDChangeLog;
class QAction;
class QDomDocument;
class QDomElement;
class QStyleOptionGraphicsItem;
......@@ -29,8 +30,8 @@ class DiagramProxyWidget {
public:
DiagramProxyWidget(UMLWidget *widget, qreal borderWidth = 5);
virtual ~DiagramProxyWidget() {}
Uml::ID::Type diagramLink();
UMLScene *linkedDiagram();
Uml::ID::Type diagramLink() const;
UMLScene *linkedDiagram() const;
bool setDiagramLink(const Uml::ID::Type &id);
const QRectF &clientRect();
const QRectF &sceneRect();
......@@ -43,6 +44,13 @@ public:
QPointF mapToClient(const QPointF &pos);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
bool showLinkedDiagram() const;
void setShowLinkedDiagram(bool showLinkedDiagram);
QRectF iconRect() const;
void setIconRect(const QRectF &iconRect);
protected:
DiagramProxyWidget& operator=(const DiagramProxyWidget& other);
bool activate(IDChangeLog* changeLog = 0);
......@@ -55,14 +63,17 @@ protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void slotMenuSelection(QAction *action);
private:
Uml::ID::Type m_diagramLinkId; ///< id of linked diagram
QPointer<UMLScene> m_linkedDiagram; ///< pointer to linked diagram
QRectF m_clientRect; ///< widget area for embedded diagram
QRectF m_sceneRect; ///< scene rectangle used for internal calculations
QRectF m_iconRect; ///< widget area for diagram icon
UMLWidget *m_widget;
qreal m_borderWidth;
bool m_showLinkedDiagram;
};
#endif // DIAGRAMPROXYWIDGET_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment