diff --git a/umbrello/menus/listpopupmenu.cpp b/umbrello/menus/listpopupmenu.cpp index 7262addcc..a8890a563 100644 --- a/umbrello/menus/listpopupmenu.cpp +++ b/umbrello/menus/listpopupmenu.cpp @@ -1,629 +1,630 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2002-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ // own header #include "listpopupmenu.h" // app includes #include "activitywidget.h" #include "associationline.h" #include "associationwidget.h" #include "category.h" #include "classifier.h" #include "classifierwidget.h" #include "combinedfragmentwidget.h" #include "debug_utils.h" #include "floatingtextwidget.h" #include "folder.h" #include "forkjoinwidget.h" #include "layoutgenerator.h" #include "model_utils.h" #include "objectnodewidget.h" #include "objectwidget.h" #include "notewidget.h" #include "pinportbase.h" #include "preconditionwidget.h" #include "signalwidget.h" #include "statewidget.h" #include "uml.h" #include "umldoc.h" #include "umlscene.h" #include "umlview.h" #include "umllistview.h" #include "umllistviewitem.h" #include "widget_utils.h" #include "widgetbase.h" // kde includes #include #include DEBUG_REGISTER_DISABLED(ListPopupMenu) static const bool CHECKABLE = true; // uncomment to see not handled switch cases //#define CHECK_SWITCH class DebugMenu { public: DebugMenu(ListPopupMenu::MenuType _m) : m(_m) {} DebugMenu(const QString & _m) : menu(_m) {} ListPopupMenu::MenuType m; QString menu; }; class ListPopupMenuPrivate { public: QList debugActions; ~ListPopupMenuPrivate() { debugActions.clear(); } }; #define DEBUG_AddAction(m) d->debugActions.append(DebugMenu(m)) #define DEBUG_StartMenu(m) d->debugActions.append(DebugMenu(m->title() + QLatin1String(" - start"))) #define DEBUG_EndMenu(m) d->debugActions.append(DebugMenu(m->title() + QLatin1String(" - end"))) /** * Constructs the popup menu * * @param parent The parent to ListPopupMenu. */ ListPopupMenu::ListPopupMenu(QWidget *parent) : KMenu(parent), d(new ListPopupMenuPrivate) { } /** * Standard destructor. */ ListPopupMenu::~ListPopupMenu() { foreach (QAction* action, m_actions) { delete action; } m_actions.clear(); delete d; } KMenu *ListPopupMenu::newMenu(const QString &title, QWidget *widget) { KMenu *menu = new KMenu(title, widget); DEBUG_StartMenu(menu); return menu; } void ListPopupMenu::addMenu(KMenu *menu) { KMenu::addMenu(menu); DEBUG_EndMenu(menu); } /** * Shortcut for the frequently used addAction() calls. * * @param m The MenuType for which to insert a menu item. */ void ListPopupMenu::insert(MenuType m) { insert(m, this); } /** * Shortcut for the frequently used addAction() calls. * * @param m The MenuType for which to insert a menu item. * @param menu The KMenu for which to insert a menu item. * @param s The entry to be inserted from the action collection */ void ListPopupMenu::insertFromActionKey(const MenuType m, KMenu *menu, const QString &s) { QAction* action = UMLApp::app()->actionCollection()->action(s); insert(m, menu, action->icon(), action->text()); } /** * Shortcut for the frequently used addAction() calls. * * @param m The MenuType for which to insert a menu item. * @param menu The KMenu for which to insert a menu item. */ void ListPopupMenu::insert(const MenuType m, KMenu* menu) { DEBUG_AddAction(m); Q_ASSERT(menu != 0); switch (m) { case mt_Accept_Signal: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Accept_Signal), i18n("Accept Signal")); break; case mt_Accept_Time_Event: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Accept_TimeEvent), i18n("Accept Time Event")); break; case mt_Activity: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_UseCase), i18n("Activity...")); break; case mt_Activity_Transition: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Activity_Transition), i18n("Activity Transition")); break; case mt_Actor: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Actor), i18n("Actor")); break; //case mt_Actor: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Actor), i18n("Actor...")); break; case mt_Artifact: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Artifact), i18n("Artifact")); break; //case mt_Artifact: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Artifact), i18n("Artifact...")); break; case mt_Attribute: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Public_Attribute), i18n("Attribute")); break; //case mt_Attribute: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Public_Attribute), i18n("Attribute...")); break; case mt_Branch: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Branch), i18n("Branch/Merge")); break; case mt_Category: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Category), i18n("Category")); break; //case mt_Category: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Category), i18n("Category...")); break; case mt_Change_Font: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Change_Font), i18n("Change Font...")); break; case mt_CheckConstraint: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Constraint_Check), i18n("Check Constraint...")); break; case mt_Choice: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Choice_Rhomb), i18n("Choice")); break; case mt_Class: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Class), i18nc("new class menu item", "Class...")); break; case mt_Clone: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Duplicate), i18nc("duplicate action", "Duplicate")); break; case mt_Collapse_All: m_actions[m] = menu->addAction(i18n("Collapse All")); break; case mt_CombinedState: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_State), i18nc("add new combined state", "Combined state...")); break; case mt_Component: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Component), i18n("Component")); break; //case mt_Component: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Component), i18n("Component...")); break; case mt_Component_Diagram: insertFromActionKey(m, menu, QLatin1String("new_component_diagram")); break; case mt_Component_Folder: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Folder), i18n("Folder")); break; case mt_Copy: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Copy), i18n("Copy")); break; case mt_Cut: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Cut), i18n("Cut")); break; case mt_Datatype: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Datatype), i18n("Datatype...")); break; case mt_DeepHistory: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_History_Deep), i18n("Deep History")); break; case mt_Delete: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Delete), i18n("Delete")); break; case mt_Deployment_Diagram: insertFromActionKey(m, menu, QLatin1String("new_deployment_diagram")); break; case mt_Deployment_Folder: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Folder), i18n("Folder")); break; + case mt_EditCombinedState: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_State), i18n("Edit combined state")); break; case mt_End_Activity: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_EndState), i18n("End Activity")); break; case mt_End_State: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_EndState), i18n("End State")); break; case mt_Entity: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Entity), i18n("Entity")); break; //case mt_Entity: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Entity), i18n("Entity...")); break; case mt_EntityAttribute: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Entity_Attribute), i18n("Entity Attribute...")); break; case mt_EntityRelationship_Diagram: insertFromActionKey(m, menu, QLatin1String("new_entityrelationship_diagram")); break; case mt_EntityRelationship_Folder: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Folder), i18n("Folder")); break; case mt_Enum: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Enum), i18n("Enum...")); break; case mt_EnumLiteral: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Enum_Literal), i18n("Enum Literal...")); break; case mt_Exception: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Exception), i18n("Exception")); break; case mt_Expand_All: m_actions[m] = menu->addAction(i18n("Expand All")); break; case mt_Export_Image: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Export_Picture), i18n("Export as Picture...")); break; case mt_Externalize_Folder: m_actions[m] = menu->addAction(i18n("Externalize Folder...")); break; case mt_Fill_Color: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Color_Fill), i18n("Fill Color...")); break; case mt_Final_Activity: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Activity_Final), i18n("Final Activity")); break; case mt_FlipHorizontal: m_actions[m] = menu->addAction(i18n("Flip Horizontal")); break; case mt_FlipVertical: m_actions[m] = menu->addAction(i18n("Flip Vertical")); break; 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_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; case mt_Initial_Activity: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_InitialState), i18n("Initial Activity")); break; case mt_Initial_State: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_InitialState), i18n("Initial State")); break; case mt_Instance: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Instance), i18nc("new instance menu item", "Instance...")); break; case mt_InstanceAttribute: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Attribute_New), i18n("New Attribute...")); break; case mt_Interface: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Interface), i18n("Interface")); break; case mt_InterfaceComponent: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Interface_Provider), i18n("Interface")); break; case mt_InterfaceProvided: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Interface_Provider), i18n("Provided interface")); break; case mt_InterfaceRequired: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Interface_Requirement), i18n("Required interface")); break; case mt_Internalize_Folder: m_actions[m] = menu->addAction(i18n("Internalize Folder")); break; case mt_Junction: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Junction), i18n("Junction")); break; case mt_Line_Color: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Color_Line), i18n("Line Color...")); break; case mt_Logical_Folder: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Folder), i18n("Folder")); break; case mt_MessageAsynchronous: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Message_Async), i18n("Asynchronous Message")); break; case mt_MessageFound: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Message_Found), i18n("Found Message")); break; case mt_MessageLost: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Message_Lost), i18n("Lost Message")); break; case mt_MessageSynchronous: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Message_Sync), i18n("Synchronous Message")); break; case mt_New_Activity: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_State_Activity), i18n("Activity...")); break; case mt_New_Attribute: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Attribute_New), i18n("New Attribute...")); break; case mt_New_EntityAttribute: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Entity_Attribute_New), i18n("New Entity Attribute...")); break; case mt_New_EnumLiteral: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Literal_New), i18n("New Literal...")); break; case mt_New_InstanceAttribute: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Attribute_New), i18n("New Attribute...")); break; case mt_New_Operation: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Operation_Public_New), i18n("New Operation...")); break; case mt_New_Parameter: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Parameter_New), i18n("New Parameter...")); break; case mt_New_Template: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Template_New), i18n("New Template...")); break; case mt_Node: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Node), i18n("Node")); break; //case mt_Node: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Node), i18n("Node...")); break; case mt_Note: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Note), i18n("Note...")); break; //case mt_Note: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Note), i18n("Note...")); break; case mt_Object: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Object), i18n("Object...")); break; case mt_Object_Node: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Object_Node), i18n("Object Node")); break; case mt_Open_File: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_File_Open), i18n("Open file")); break; case mt_Operation: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Public_Method), i18n("Operation")); break; //case mt_Operation: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Public_Method), i18n("Operation...")); break; case mt_Package: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Package), i18n("Package...")); break; case mt_Paste: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Paste), i18n("Paste")); break; case mt_Pin: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Pin), i18n("Pin")); break; case mt_Port: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Port), i18n("Port")); break; //case mt_Port: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Port), i18n("Port...")); break; case mt_PrePostCondition: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Condition_PrePost), i18n("Pre Post Condition")); break; case mt_PrimaryKeyConstraint: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Constraint_PrimaryKey), i18n("Primary Key Constraint...")); break; case mt_Properties: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Properties), i18n("Properties")); break; 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_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_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; case mt_ShallowHistory: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_History_Shallow), i18n("Shallow History")); break; case mt_Show: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Show), i18n("Show")); break; case mt_State: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_State), i18nc("add new state", "State...")); break; 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_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; //case mt_Template: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Template_New), i18n("Template...")); break; case mt_Undo: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Undo), i18n("Undo")); break; case mt_UniqueConstraint: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Constraint_Unique), i18n("Unique Constraint...")); break; case mt_UseCase: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_UseCase), i18n("Use Case")); break; //case mt_UseCase: m_actions[m] = menu->addAction(Icon_Utils::SmallIcon(Icon_Utils::it_UseCase), i18n("Use Case...")); break; case mt_UseCase_Diagram: insertFromActionKey(m, menu, QLatin1String("new_use_case_diagram")); break; case mt_UseCase_Folder: m_actions[m] = menu->addAction(Icon_Utils::BarIcon(Icon_Utils::it_Folder), i18n("Folder")); break; default: uWarning() << "called on unimplemented MenuType " << toString(m); break; } } /** * Shortcut for the frequently used addAction() calls. * * @param m The MenuType for which to insert a menu item. * @param icon The icon for this action. * @param text The text for this action. */ void ListPopupMenu::insert(const MenuType m, const QIcon & icon, const QString & text) { DEBUG_AddAction(m); m_actions[m] = addAction(icon, text); } /** * Shortcut for the frequently used addAction() calls. * * @param m The MenuType for which to insert a menu item. * @param text The text for this action. * @param checkable Sets the action to checkable. */ void ListPopupMenu::insert(const MenuType m, const QString & text, const bool checkable) { insert(m, this, text, checkable); } /** * Shortcut for the frequently used addAction() calls. * * @param m The MenuType for which to insert a menu item. * @param menu The KMenu for which to insert a menu item. * @param icon The icon for this action. * @param text The text for this action. */ void ListPopupMenu::insert(const MenuType m, KMenu* menu, const QIcon & icon, const QString & text) { DEBUG_AddAction(m); m_actions[m] = menu->addAction(icon, text); } /** * Shortcut for the frequently used addAction() calls. * * @param m The MenuType for which to insert a menu item. * @param menu The KMenu for which to insert a menu item. * @param text The text for this action. * @param checkable Sets the action to checkable. */ void ListPopupMenu::insert(const MenuType m, KMenu* menu, const QString & text, const bool checkable) { DEBUG_AddAction(m); m_actions[m] = menu->addAction(text); if (checkable) { QAction* action = getAction(m); if (action) action->setCheckable(checkable); } } /** * Shortcut for inserting standard model items (Class, Interface, * Datatype, Enum, Package) as well as diagram choices. * * @param folderAndDiagrams Set this true if folders and diagram * types shall be included as choices. * @param packages Set this true if packages * shall be included as choices. */ void ListPopupMenu::insertContainerItems(bool folderAndDiagrams, bool packages) { KMenu* menu = newMenu(i18nc("new container menu", "New"), this); menu->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_New)); insertContainerItems(menu, folderAndDiagrams, packages); addMenu(menu); } /** * Shortcut for inserting standard model items (Class, Interface, * Datatype, Enum, Package) as well as diagram choices. * * @param menu Menu to add the menu entries * @param folderAndDiagrams Set this true if folders and diagram * types shall be included as choices. * @param packages Set this true if packages * shall be included as choices. */ void ListPopupMenu::insertContainerItems(KMenu* menu, bool folderAndDiagrams, bool packages) { if (folderAndDiagrams) insert(mt_Logical_Folder, menu, Icon_Utils::BarIcon(Icon_Utils::it_Folder), i18n("Folder")); insert(mt_Class, menu); insert(mt_Interface); insert(mt_Datatype); insert(mt_Enum); if (packages) insert(mt_Package); if (folderAndDiagrams) { insertFromActionKey(mt_Class_Diagram, menu, QLatin1String("new_class_diagram")); insertFromActionKey(mt_Sequence_Diagram, menu, QLatin1String("new_sequence_diagram")); insertFromActionKey(mt_Collaboration_Diagram, menu, QLatin1String("new_collaboration_diagram")); insertFromActionKey(mt_State_Diagram, menu, QLatin1String("new_state_diagram")); insertFromActionKey(mt_Activity_Diagram, menu, QLatin1String("new_activity_diagram")); } } /** * Inserts a menu item for an association related text * (such as name, role, multiplicity etc.) * * @param label The menu text. * @param mt The menu type. */ void ListPopupMenu::insertAssociationTextItem(const QString &label, MenuType mt) { insert(mt, label); insert(mt_Change_Font); insert(mt_Reset_Label_Positions); insert(mt_Properties); } /** * Convenience method to extract the ListPopupMenu type from an action. * @param action the action which was called * @return menu type enum value */ ListPopupMenu::MenuType ListPopupMenu::typeFromAction(QAction *action) { ListPopupMenu *menu = ListPopupMenu::menuFromAction(action); if (menu) { return menu->getMenuType(action); } else { uError() << "Action's data field does not contain ListPopupMenu pointer!"; return mt_Undefined; } } /** * Utility: Convert a MenuType value to an ObjectType value. */ UMLObject::ObjectType ListPopupMenu::convert_MT_OT(MenuType mt) { UMLObject::ObjectType type = UMLObject::ot_UMLObject; switch (mt) { case mt_UseCase: type = UMLObject::ot_UseCase; break; case mt_Actor: type = UMLObject::ot_Actor; break; case mt_Class: type = UMLObject::ot_Class; break; case mt_Datatype: type = UMLObject::ot_Datatype; break; case mt_Attribute: type = UMLObject::ot_Attribute; break; case mt_Interface: type = UMLObject::ot_Interface; break; case mt_Template: type = UMLObject::ot_Template; break; case mt_Enum: type = UMLObject::ot_Enum; break; case mt_EnumLiteral: type = UMLObject::ot_EnumLiteral; break; case mt_EntityAttribute: type = UMLObject::ot_EntityAttribute; break; case mt_Operation: type = UMLObject::ot_Operation; break; case mt_Category: type = UMLObject::ot_Category; break; case mt_InstanceAttribute: type = UMLObject::ot_InstanceAttribute; break; default: break; } return type; } /** * Returns the data from the given action to the given key. */ QVariant ListPopupMenu::dataFromAction(DataType key, QAction* action) { QVariant data = action->data(); QMap map = data.toMap(); return map[ListPopupMenu::toString(key)]; } /** * Convenience method to extract the ListPopupMenu pointer stored in QAction * objects belonging to ListPopupMenu. */ ListPopupMenu* ListPopupMenu::menuFromAction(QAction *action) { if (action) { QVariant value = dataFromAction(dt_MenuPointer, action); if (value.canConvert()) { return qvariant_cast(value); } } return 0; } /** * Create the 'new' menu * @return menu instance */ KMenu *ListPopupMenu::makeNewMenu() { KMenu *menu = newMenu(i18nc("new sub menu", "New"), this); menu->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_New)); return menu; } /** * Creates a popup menu for a single category Object * @param category The UMLCategory for which the category menu is created */ void ListPopupMenu::insertSubMenuCategoryType(UMLCategory* category) { KMenu* menu = newMenu(i18nc("category type sub menu", "Category Type"), this); insert(mt_DisjointSpecialisation, menu, i18n("Disjoint(Specialisation)"), CHECKABLE); insert(mt_OverlappingSpecialisation, menu, i18n("Overlapping(Specialisation)"), CHECKABLE); insert(mt_Union, menu, i18n("Union"), CHECKABLE); setActionChecked(mt_DisjointSpecialisation, category->getType()==UMLCategory::ct_Disjoint_Specialisation); setActionChecked(mt_OverlappingSpecialisation, category->getType()==UMLCategory::ct_Overlapping_Specialisation); setActionChecked(mt_Union, category->getType()==UMLCategory::ct_Union); addMenu(menu); } /** * Get the action from the menu type as index. */ QAction* ListPopupMenu::getAction(MenuType idx) { return m_actions.value(idx, 0); } // /** // * Get the MenuType from the action. // */ // ListPopupMenu::MenuType ListPopupMenu::getMenuType(KAction* action) // { // return m_actions.key(action); // } /** * Get the MenuType from the action. */ ListPopupMenu::MenuType ListPopupMenu::getMenuType(QAction* action) { QList keyList = m_actions.keys(action); if (keyList.empty() || /* all key-value pairs are unique*/ keyList.count() > 1) { return mt_Undefined; } else { // we return the first (only) value return keyList.first(); } } /** * Checks the action item. * * @param idx The MenuType for which to check the menu item. * @param value The value. */ void ListPopupMenu::setActionChecked(MenuType idx, bool value) { QAction* action = getAction(idx); if (action && action->isCheckable()) { action->setChecked(value); } else { DEBUG(DBG_SRC) << "called on unknown MenuType " << toString(idx); } } /** * Enables the action item. * * @param idx The MenuType for which to enable the menu item. * @param value The value. */ void ListPopupMenu::setActionEnabled(MenuType idx, bool value) { QAction* action = getAction(idx); if (action) { action->setEnabled(value); } else { DEBUG(DBG_SRC) << "called on unknown MenuType " << toString(idx); } } /** * Sets up actions added to the ListPopupMenu to have their data field set to * pointer to this ListPopupMenu object, so that this menu pointer can be * retrieved in UMLWidget::slotMenuSelection * * @note This might seem like an ugly hack, but this is the only solution which * helped in avoiding storage of ListPopupMenu pointer in each UMLWidget. */ void ListPopupMenu::setupActionsData() { foreach (QAction *action, m_actions) { QMap map = action->data().toMap(); map[toString(dt_MenuPointer)] = qVariantFromValue(this); action->setData(QVariant(map)); } } /** * Convert enum MenuType to string. */ QString ListPopupMenu::toString(MenuType menu) { return QLatin1String(ENUM_NAME(ListPopupMenu, MenuType, menu)); } /** * Convert enum DataType to string. */ QString ListPopupMenu::toString(DataType data) { return QLatin1String(ENUM_NAME(ListPopupMenu, DataType, data)); } //QList &ListPopupMenu::debugActions() //{ // return d->debugActions; //} /** * dump collected actions * @param title optional menu title */ void ListPopupMenu::dumpActions(const QString &title) { qDebug().nospace() << title; foreach(DebugMenu e, d->debugActions) { if (!e.menu.isEmpty()) qDebug().nospace() << " " << e.menu; else qDebug().nospace() << " " << toString(e.m); } } diff --git a/umbrello/menus/listpopupmenu.h b/umbrello/menus/listpopupmenu.h index bee7ac6b3..1ed46d459 100644 --- a/umbrello/menus/listpopupmenu.h +++ b/umbrello/menus/listpopupmenu.h @@ -1,311 +1,312 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2003-2018 * * Umbrello UML Modeller Authors * ***************************************************************************/ #ifndef LISTPOPUPMENU_H #define LISTPOPUPMENU_H #include "basictypes.h" #include "umllistviewitem.h" #include "umlobject.h" #include "widgetbase.h" #include #include class UMLCategory; class ListPopupMenuPrivate; /** * A popup menu that depending on what type is set to will * display a different menu. * * The data field of actions is used to carry user data * between objects. Because different types of data are used, a map is loaded * with an enum as key (see @ref DataType). * * @short Displays a popup menu. * @author Paul Hensgen * Bugs and comments to umbrello-devel@kde.org or http://bugs.kde.org */ class ListPopupMenu : public KMenu { Q_OBJECT Q_ENUMS(MenuType) Q_ENUMS(DataType) public: enum MenuType ///< This type hosts all possible menu entry types { mt_Model, // diagrams mt_Activity_Diagram, mt_Class_Diagram, mt_Collaboration_Diagram, mt_Component_Diagram, mt_Deployment_Diagram, mt_EntityRelationship_Diagram, mt_Sequence_Diagram, mt_State_Diagram, mt_UseCase_Diagram, mt_Logical_Folder, mt_UseCase_Folder, mt_Component_Folder, mt_Deployment_Folder, mt_EntityRelationship_Folder, // widgets, uml objects mt_Accept_Signal, mt_Accept_Time_Event, mt_Activity, mt_Activity_Transition, mt_Actor, mt_Artifact, mt_Attribute, mt_Branch, mt_Category, mt_CheckConstraint, mt_Choice, mt_Class, mt_CombinedState, mt_Component, mt_Datatype, mt_DeepHistory, mt_DisjointSpecialisation, + mt_EditCombinedState, mt_End_Activity, mt_End_State, mt_Entity, mt_EntityAttribute, mt_Enum, mt_EnumLiteral, mt_Exception, mt_FloatText, mt_Final_Activity, mt_ForeignKeyConstraint, mt_Fork, mt_Initial_Activity, mt_Initial_State, mt_Invoke_Activity, mt_Instance, mt_InstanceAttribute, mt_Interface, mt_InterfaceComponent, mt_InterfaceProvided, mt_InterfaceRequired, mt_Junction, mt_MessageAsynchronous, mt_MessageFound, mt_MessageLost, mt_MessageSynchronous, mt_Node, mt_Note, mt_Object, mt_Object_Node, mt_Operation, mt_OverlappingSpecialisation, mt_Package, mt_Param_Activity, mt_Pin, mt_Port, mt_PrePostCondition, mt_PrimaryKeyConstraint, mt_Region, mt_Send_Signal, mt_ShallowHistory, mt_State, mt_StateFork, mt_StateJoin, mt_StateTransition, mt_Subsystem, mt_Template, mt_Union, mt_UniqueConstraint, mt_UseCase, // new from dialogs mt_New_Activity, mt_New_Attribute, mt_New_EntityAttribute, mt_New_EnumLiteral, mt_New_InstanceAttribute, mt_New_Operation, mt_New_Parameter, mt_New_Template, // selection // visual properties mt_Hide_Attribute_Signature_Selection, mt_Hide_Attributes_Selection, // Unset visual property on multiple widgets mt_Hide_NonPublic_Selection, // Could be named "show public only" mt_Hide_Operation_Signature_Selection, mt_Hide_Operations_Selection, // Hide operations mt_Hide_Packages_Selection, mt_Hide_Stereotypes_Selection, mt_Hide_Visibility_Selection, mt_Show_Attribute_Signature, mt_Show_Attribute_Signature_Selection, mt_Show_Attributes_Selection, // Set visual property on multiple widgets mt_Show_Attributes, // Toggle visual property on a widget mt_Show_Documentation, mt_Show_NonPublic_Selection, // Could be named "hide public only" (crazy!) mt_Show_Operation_Signature, mt_Show_Operation_Signature_Selection, mt_Show_Operations_Selection, // Show operations mt_Show_Operations, // Toggle 'show operations' mt_Show_Packages, // etc... mt_Show_Packages_Selection, mt_Show_Public_Only, mt_Show_Stereotypes, mt_Show_Stereotypes_Selection, mt_Show_Visibility_Selection, mt_Visibility, // other mt_DrawAsCircle, mt_ChangeToClass, mt_ChangeToInterface, mt_ChangeToPackage, mt_Open_File, mt_Rename_Object, mt_Select_Operation, mt_Properties, mt_Rename, mt_NameAsTooltip, mt_Show, mt_Delete, mt_Export_Image, mt_Import_Class, mt_Import_Project, mt_Cut, mt_Copy, mt_Paste, mt_Clear, mt_Redo, mt_Undo, mt_Reset_Label_Positions, mt_Line_Color, mt_Line_Color_Selection, mt_Fill_Color, mt_Fill_Color_Selection, mt_Use_Fill_Color, mt_Set_Use_Fill_Color_Selection, mt_Unset_Use_Fill_Color_Selection, mt_Rename_MultiA, mt_Rename_MultiB, mt_Rename_Name, mt_Rename_RoleAName, mt_Rename_RoleBName, mt_Change_Font, mt_Change_Font_Selection, mt_SnapToGrid, mt_SnapComponentSizeToGrid, mt_ShowDocumentationIndicator, mt_ShowSnapGrid, mt_AutoResize, mt_Resize, mt_Up, mt_Down, mt_FlipHorizontal, mt_FlipVertical, mt_Add_Point, mt_Delete_Point, mt_Auto_Layout_Spline, mt_Expand_All, // Expand all items in the list mt_Collapse_All, // Collapse all items in the list mt_Refactoring, mt_ViewCode, // view code document contents mt_Clone, // Create a deep copy of the object. mt_Externalize_Folder, // Mark folder for saving as separate submodel mt_Internalize_Folder, // Reintegrate separate submodel into main model mt_AddInteractionOperand, // add a dash line to an alternative or a parallel combined fragment mt_Apply_Layout, // apply automatically created layout mt_Apply_Layout1, // apply automatically created layout mt_Apply_Layout2, // apply automatically created layout mt_Apply_Layout3, // apply automatically created layout mt_Apply_Layout4, // apply automatically created layout mt_Apply_Layout5, // apply automatically created layout mt_Apply_Layout6, // apply automatically created layout mt_Apply_Layout7, // apply automatically created layout mt_Apply_Layout8, // apply automatically created layout mt_Apply_Layout9, // apply automatically created layout mt_LayoutDirect, // associations with direct lines mt_LayoutSpline, // associations with slines mt_LayoutOrthogonal, // associations with orthogonal lines mt_LayoutPolyline, // associations with polylines mt_Align_Right, mt_Align_Left, mt_Align_Top, mt_Align_Bottom, mt_Align_VerticalMiddle, mt_Align_HorizontalMiddle, mt_Align_VerticalDistribute, mt_Align_HorizontalDistribute, mt_Import_from_File, mt_Remove, // add new entries above mt_Undefined = - 1 }; static QString toString(MenuType menu); enum DataType ///< Key value of the data map used in actions. { dt_MenuPointer, dt_ApplyLayout }; static QString toString(DataType data); static QVariant dataFromAction(DataType key, QAction* action); ListPopupMenu(QWidget* parent = 0); virtual ~ListPopupMenu(); static UMLObject::ObjectType convert_MT_OT(MenuType mt); static ListPopupMenu* menuFromAction(QAction *action); static MenuType typeFromAction(QAction *action); QAction* getAction(MenuType idx); void setActionEnabled(MenuType idx, bool value); MenuType getMenuType(QAction* action); void dumpActions(const QString &title); KMenu *newMenu(const QString &title, QWidget *widget); void addMenu(KMenu *menu); protected: void insert(MenuType m); void insertFromActionKey(const MenuType m, KMenu *menu, const QString &action); void insert(const MenuType m, KMenu* menu); void insert(const MenuType m, KMenu* menu, const QIcon & icon, const QString & text); void insert(const MenuType m, KMenu* menu, const QString & text, const bool checkable = false); void insert(const MenuType m, const QIcon & icon, const QString & text); void insert(const MenuType m, const QString & text, const bool checkable = false); void insertContainerItems(bool folderAndDiagrams, bool packages=true); void insertContainerItems(KMenu* menu, bool folderAndDiagrams, bool packages); void insertAssociationTextItem(const QString &label, MenuType mt); KMenu *makeNewMenu(); void insertSubMenuCategoryType(UMLCategory *category); void setActionChecked(MenuType idx, bool value); void setupActionsData(); QHash m_actions; ListPopupMenuPrivate *d; }; /// Need this for ability to store ListPopupMenu* in a QVariant Q_DECLARE_METATYPE(ListPopupMenu*) #endif diff --git a/umbrello/menus/widgetbasepopupmenu.cpp b/umbrello/menus/widgetbasepopupmenu.cpp index e7497e49d..34dba7aae 100644 --- a/umbrello/menus/widgetbasepopupmenu.cpp +++ b/umbrello/menus/widgetbasepopupmenu.cpp @@ -1,707 +1,715 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2018 * * Umbrello UML Modeller Authors * ***************************************************************************/ #include "widgetbasepopupmenu.h" // app includes #include "activitywidget.h" #include "category.h" #include "classifier.h" #include "combinedfragmentwidget.h" #include "debug_utils.h" #include "entitywidget.h" #include "floatingtextwidget.h" #include "forkjoinwidget.h" #include "interfacewidget.h" #include "notewidget.h" #include "objectwidget.h" #include "objectnodewidget.h" #include "pinportbase.h" #include "statewidget.h" #include "uml.h" #include "umllistview.h" #include "umlscene.h" // kde includes #include static const bool CHECKABLE = true; /** * Constructs the popup menu for a scene widget. * * @param parent The parent to ListPopupMenu. * @param widget The WidgetBase to represent a menu for. * @param multi True if multiple items are selected. * @param uniqueType The type of widget shared by all selected widgets */ WidgetBasePopupMenu::WidgetBasePopupMenu(QWidget * parent, WidgetBase * widget, bool multi, WidgetBase::WidgetType uniqueType) : ListPopupMenu(parent) { if (!widget) return; if (multi) { insertMultiSelectionMenu(uniqueType); } else { insertSingleSelectionMenu(widget); } bool bCutState = UMLApp::app()->isCutCopyState(); setActionEnabled(mt_Cut, bCutState); setActionEnabled(mt_Copy, bCutState); bool pasteAvailable = false; if (widget->isNoteWidget() && UMLApp::app()->listView()->startedCopy()) { NoteWidget::s_pCurrentNote = widget->asNoteWidget(); pasteAvailable = true; } setActionEnabled(mt_Paste, pasteAvailable); setActionChecked(mt_AutoResize, widget->autoResize()); setupActionsData(); } /** * Creates the "Show" submenu in the context menu of one classifier widget */ void WidgetBasePopupMenu::makeClassifierShowPopup(ClassifierWidget *c) { WidgetBase::WidgetType type = c->baseType(); KMenu* show = newMenu(i18n("Show"), this); show->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Show)); #ifdef ENABLE_WIDGET_SHOW_DOC insert(mt_Show_Documentation, show, i18n("Documentation"), CHECKABLE); setActionChecked(mt_Show_Documentation, c->visualProperty(ClassifierWidget::ShowDocumentation)); #endif if (type == WidgetBase::wt_Class) { insert(mt_Show_Attributes, show, i18n("Attributes"), CHECKABLE); setActionChecked(mt_Show_Attributes, c->visualProperty(ClassifierWidget::ShowAttributes)); } insert(mt_Show_Operations, show, i18n("Operations"), CHECKABLE); setActionChecked(mt_Show_Operations, c->visualProperty(ClassifierWidget::ShowOperations)); insert(mt_Show_Public_Only, show, i18n("Public Only"), CHECKABLE); setActionChecked(mt_Show_Public_Only, c->visualProperty(ClassifierWidget::ShowPublicOnly)); insert(mt_Visibility, show, i18n("Visibility"), CHECKABLE); setActionChecked(mt_Visibility, c->visualProperty(ClassifierWidget::ShowVisibility)); insert(mt_Show_Operation_Signature, show, i18n("Operation Signature"), CHECKABLE); bool sig = (c->operationSignature() == Uml::SignatureType::SigNoVis || c->operationSignature() == Uml::SignatureType::ShowSig); setActionChecked(mt_Show_Operation_Signature, sig); if (type == WidgetBase::wt_Class) { insert(mt_Show_Attribute_Signature, show, i18n("Attribute Signature"), CHECKABLE); sig = (c->attributeSignature() == Uml::SignatureType::SigNoVis || c->attributeSignature() == Uml::SignatureType::ShowSig); setActionChecked(mt_Show_Attribute_Signature, sig); } insert(mt_Show_Packages, show, i18n("Package"), CHECKABLE); setActionChecked(mt_Show_Packages, c->visualProperty(ClassifierWidget::ShowPackage)); insert(mt_Show_Stereotypes, show, i18n("Stereotype"), CHECKABLE); setActionChecked(mt_Show_Stereotypes, c->visualProperty(ClassifierWidget::ShowStereotype)); addMenu(show); } /** * Creates the "Show" submenu the context menu of multiple classifier widgets */ void WidgetBasePopupMenu::makeMultiClassifierShowPopup(WidgetBase::WidgetType type) { KMenu* show = newMenu(i18n("Show"), this); show->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Show)); KMenu* attributes = newMenu(i18n("Attributes"), this); if (type == WidgetBase::wt_Class) { insert(mt_Show_Attributes_Selection, attributes, i18n("Show")); insert(mt_Hide_Attributes_Selection, attributes, i18n("Hide")); insert(mt_Show_Attribute_Signature_Selection, attributes, i18n("Show Signatures")); insert(mt_Hide_Attribute_Signature_Selection, attributes, i18n("Hide Signatures")); } show->addMenu(attributes); KMenu* operations = newMenu(i18n("Operations"), this); insert(mt_Show_Operations_Selection, operations, i18n("Show")); insert(mt_Hide_Operations_Selection, operations, i18n("Hide")); insert(mt_Show_Operation_Signature_Selection, operations, i18n("Show Signatures")); insert(mt_Hide_Operation_Signature_Selection, operations, i18n("Hide Signatures")); show->addMenu(operations); KMenu* visibility = newMenu(i18n("Visibility"), this); insert(mt_Show_Visibility_Selection, visibility, i18n("Show")); insert(mt_Hide_Visibility_Selection, visibility, i18n("Hide")); insert(mt_Hide_NonPublic_Selection, visibility, i18n("Hide Non-public members")); insert(mt_Show_NonPublic_Selection, visibility, i18n("Show Non-public members")); show->addMenu(visibility); KMenu* packages = newMenu(i18n("Packages"), this); insert(mt_Show_Packages_Selection, packages, i18n("Show")); insert(mt_Hide_Packages_Selection, packages, i18n("Hide")); show->addMenu(packages); if (type == WidgetBase::wt_Class) { KMenu* stereotypes = newMenu(i18n("Stereotypes"), this); insert(mt_Show_Stereotypes_Selection, stereotypes, i18n("Show")); insert(mt_Hide_Stereotypes_Selection, stereotypes, i18n("Hide")); show->addMenu(stereotypes); } addMenu(show); } /** * Inserts the menu actions for a widget * * @param widget widget to generate the menu for */ void WidgetBasePopupMenu::insertSingleSelectionMenu(WidgetBase* widget) { WidgetBase::WidgetType type = widget->baseType(); switch (type) { case WidgetBase::wt_Actor: case WidgetBase::wt_UseCase: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Category: { insertSubMenuNew(type); insertSubMenuCategoryType(widget->umlObject()->asUMLCategory()); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); break; } case WidgetBase::wt_Class: { ClassifierWidget* c = widget->asClassifierWidget(); if (!c) break; insertSubMenuNew(type); makeClassifierShowPopup(c); insertSubMenuColor(c->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); if (c->umlObject() && c->umlObject()->stereotype() == QLatin1String("class-or-package")) { insert(mt_ChangeToClass, i18n("Change into Class")); insert(mt_ChangeToPackage, i18n("Change into Package")); } else { insert(mt_Refactoring, Icon_Utils::SmallIcon(Icon_Utils::it_Refactor), i18n("Refactor")); insert(mt_ViewCode, Icon_Utils::SmallIcon(Icon_Utils::it_View_Code), i18n("View Code")); UMLClassifier *umlc = c->classifier(); if (umlc->isAbstract() && umlc->getAttributeList().size() == 0) insert(mt_ChangeToInterface, i18n("Change into Interface")); } insert(mt_Properties); } break; case WidgetBase::wt_Interface: { InterfaceWidget* c = widget->asInterfaceWidget(); if (!c) break; insertSubMenuNew(type); makeClassifierShowPopup(c); insertSubMenuColor(c->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_DrawAsCircle, i18n("Draw as Circle"), CHECKABLE); setActionChecked(mt_DrawAsCircle, c->visualProperty(ClassifierWidget::DrawAsCircle)); insert(mt_ChangeToClass, i18n("Change into Class")); insert(mt_Properties); } break; case WidgetBase::wt_Instance: insertSubMenuNew(type); insert(mt_InstanceAttribute); insert(mt_Rename_Object); insert(mt_Rename, i18n("Rename Class...")); insertStdItems(true, type); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Enum: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Entity: insertSubMenuNew(type); insertSubMenuShowEntity(widget->asEntityWidget()); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Datatype: case WidgetBase::wt_Package: case WidgetBase::wt_Component: case WidgetBase::wt_Node: case WidgetBase::wt_Artifact: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(false, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Port: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(false); insert(mt_NameAsTooltip, i18n("Name as Tooltip"), true); { PinPortBase *pW = static_cast(widget); FloatingTextWidget *ft = pW->floatingTextWidget(); if (ft == 0) m_actions[mt_NameAsTooltip]->setChecked(true); } insert(mt_Delete); insert(mt_Properties); break; case WidgetBase::wt_Object: //Used for sequence diagram and collaboration diagram widgets insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); if (widget->umlScene() && widget->umlScene()->isSequenceDiagram()) { addSeparator(); MenuType tabUp = mt_Up; insert(mt_Up, Icon_Utils::SmallIcon(Icon_Utils::it_Arrow_Up), i18n("Move Up")); insert(mt_Down, Icon_Utils::SmallIcon(Icon_Utils::it_Arrow_Down), i18n("Move Down")); if (!(static_cast(widget))->canTabUp()) { setActionEnabled(tabUp, false); } } insertStdItems(true, type); insert(mt_Rename_Object); insert(mt_Rename, i18n("Rename Class...")); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Message: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(false, type); //insert(mt_Change_Font); //insert(mt_Operation, Icon_Utils::SmallIcon(Icon_Utils::it_Operation_New), i18n("New Operation...")); //insert(mt_Select_Operation, i18n("Select Operation...")); break; case WidgetBase::wt_Note: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); insert(mt_Clear, Icon_Utils::SmallIcon(Icon_Utils::it_Clear), i18nc("clear note", "Clear")); addSeparator(); insert(mt_Rename, i18n("Change Text...")); insert(mt_Resize); insert(mt_AutoResize, i18n("Auto resize"), CHECKABLE); insert(mt_Delete); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Box: insertSubMenuNew(type); insertStdItems(false, type); insert(mt_Line_Color); break; case WidgetBase::wt_State: { StateWidget* pState = static_cast< StateWidget *>(widget); + switch (pState->stateType()) { + case StateWidget::Combined: + insert(mt_EditCombinedState); + break; + default: + break; + } + insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(false, type); switch (pState->stateType()) { case StateWidget::Normal: insert(mt_Rename, i18n("Change State Name...")); insert(mt_Change_Font); insert(mt_Properties); break; case StateWidget::Fork: case StateWidget::Join: insert(pState->drawVertical() ? mt_FlipHorizontal : mt_FlipVertical); break; default: break; } } break; case WidgetBase::wt_ForkJoin: insertSubMenuNew(type); { ForkJoinWidget *pForkJoin = static_cast(widget); insert(pForkJoin->orientation() == Qt::Vertical ? mt_FlipHorizontal : mt_FlipVertical); insert(mt_Fill_Color); } break; case WidgetBase::wt_Activity: insertSubMenuNew(type); { ActivityWidget* pActivity = static_cast(widget); if(pActivity->activityType() == ActivityWidget::Normal || pActivity->activityType() == ActivityWidget::Invok || pActivity->activityType() == ActivityWidget::Param) { insertSubMenuColor(widget->useFillColor()); } insertStdItems(false, type); if(pActivity->activityType() == ActivityWidget::Normal || pActivity->activityType() == ActivityWidget::Invok || pActivity->activityType() == ActivityWidget::Param) { insert(mt_Rename, i18n("Change Activity Name...")); insert(mt_Change_Font); insert(mt_Properties); } } break; case WidgetBase::wt_ObjectNode: insertSubMenuNew(type); { ObjectNodeWidget* objWidget = static_cast(widget); if (objWidget->objectNodeType() == ObjectNodeWidget::Buffer || objWidget->objectNodeType() == ObjectNodeWidget::Data || objWidget->objectNodeType() == ObjectNodeWidget::Flow) { insertSubMenuColor(widget->useFillColor()); } insertStdItems(false, type); if (objWidget->objectNodeType() == ObjectNodeWidget::Buffer || objWidget->objectNodeType() == ObjectNodeWidget::Data || objWidget->objectNodeType() == ObjectNodeWidget::Flow) { insert(mt_Rename, i18n("Change Object Node Name...")); insert(mt_Change_Font); insert(mt_Properties); } } break; case WidgetBase::wt_Pin: case WidgetBase::wt_Signal: case WidgetBase::wt_FloatingDashLine: case WidgetBase::wt_Precondition: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); insert(mt_Clear, Icon_Utils::SmallIcon(Icon_Utils::it_Clear), i18nc("clear precondition", "Clear")); addSeparator(); insert(mt_Rename, i18n("Change Text...")); if (type == WidgetBase::wt_Pin) { insert(mt_NameAsTooltip, i18n("Name as Tooltip"), true); PinPortBase *pW = static_cast(widget); FloatingTextWidget *ft = pW->floatingTextWidget(); if (ft == 0) m_actions[mt_NameAsTooltip]->setChecked(true); } insert(mt_Delete); insert(mt_Change_Font); break; case WidgetBase::wt_CombinedFragment: insertSubMenuNew(type); // for alternative and parallel combined fragments if ((static_cast(widget))->combinedFragmentType() == CombinedFragmentWidget::Alt || (static_cast(widget))->combinedFragmentType() == CombinedFragmentWidget::Par) { insert(mt_AddInteractionOperand, i18n("Add Interaction Operand")); addSeparator(); } insertSubMenuColor(widget->useFillColor()); addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); insert(mt_Clear, Icon_Utils::SmallIcon(Icon_Utils::it_Clear), i18nc("clear combined fragment", "Clear")); addSeparator(); insert(mt_Rename, i18n("Change Text...")); insert(mt_Delete); insert(mt_Change_Font); break; case WidgetBase::wt_Text: insertSubMenuNew(type); switch((static_cast(widget))->textRole()) { case Uml::TextRole::MultiB: insertAssociationTextItem(i18n("Change Multiplicity..."), mt_Rename_MultiB); break; case Uml::TextRole::MultiA: insertAssociationTextItem(i18n("Change Multiplicity..."), mt_Rename_MultiA); break; case Uml::TextRole::Name: insertAssociationTextItem(i18n("Change Name"), mt_Rename_Name); break; case Uml::TextRole::RoleAName: insertAssociationTextItem(i18n("Change Role A Name..."), mt_Rename_RoleAName); break; case Uml::TextRole::RoleBName: insertAssociationTextItem(i18n("Change Role B Name..."), mt_Rename_RoleBName); break; case Uml::TextRole::ChangeA: case Uml::TextRole::ChangeB: insert(mt_Change_Font); insert(mt_Reset_Label_Positions); insert(mt_Properties); break; case Uml::TextRole::Coll_Message_Self: case Uml::TextRole::Coll_Message: case Uml::TextRole::Seq_Message_Self: case Uml::TextRole::Seq_Message: insert(mt_Change_Font); insert(mt_Operation, Icon_Utils::SmallIcon(Icon_Utils::it_Operation_New), i18n("New Operation...")); insert(mt_Select_Operation, i18n("Select Operation...")); break; case Uml::TextRole::Floating: default: insertStdItems(false, type); insert(mt_Rename, i18n("Change Text...")); insert(mt_Change_Font); break; } break; default: uWarning() << "unhandled WidgetType " << WidgetBase::toString(type); break; }//end switch } /** * Inserts the menu actions that work on the whole selection of widgets */ void WidgetBasePopupMenu::insertMultiSelectionMenu(WidgetBase::WidgetType uniqueType) { insertSubMenuAlign(); KMenu* color = newMenu(i18nc("color menu", "Color"), this); insert(mt_Line_Color_Selection, color, Icon_Utils::SmallIcon(Icon_Utils::it_Color_Line), i18n("Line Color...")); insert(mt_Fill_Color_Selection, color, Icon_Utils::SmallIcon(Icon_Utils::it_Color_Fill), i18n("Fill Color...")); insert(mt_Set_Use_Fill_Color_Selection, color, i18n("Use Fill Color")); insert(mt_Unset_Use_Fill_Color_Selection, color, i18n("No Fill Color")); // Add menu actions specific to classifiers if (uniqueType == WidgetBase::wt_Class || uniqueType == WidgetBase::wt_Interface) { makeMultiClassifierShowPopup(uniqueType); } addMenu(color); addSeparator(); insert(mt_Cut); insert(mt_Copy); addSeparator(); insert(mt_Clone); insert(mt_Delete); insert(mt_Resize); addSeparator(); insert(mt_Change_Font_Selection, Icon_Utils::SmallIcon(Icon_Utils::it_Change_Font), i18n("Change Font...")); } /** * Shortcut for the frequently used insert() calls. * * @param insertLeadingSeparator Set this true if the group shall * start with a separator. * @param type The WidgetType for which to insert the menu items. * If no argument is supplied then a Rename item will be * included. */ void WidgetBasePopupMenu::insertStdItems(bool insertLeadingSeparator, WidgetBase::WidgetType type) { if (insertLeadingSeparator) addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); addSeparator(); if (type == WidgetBase::wt_UMLWidget) insert(mt_Rename); else if (Model_Utils::isCloneable(type)) { insert(mt_Clone); insert(mt_Remove); } else insert(mt_Delete); insert(mt_Resize); insert(mt_AutoResize, i18n("Auto resize"), CHECKABLE); } /** * Add the align actions submenu */ void WidgetBasePopupMenu::insertSubMenuAlign() { KMenu* alignment = newMenu(i18nc("align menu", "Align"), this); insert(mt_Align_Right, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Right), i18n("Align Right")); insert(mt_Align_Left, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Left), i18n("Align Left")); insert(mt_Align_Top, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Top), i18n("Align Top")); insert(mt_Align_Bottom, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Bottom), i18n("Align Bottom")); insert(mt_Align_VerticalMiddle, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_VerticalMiddle), i18n("Align Vertical Middle")); insert(mt_Align_HorizontalMiddle, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_HorizontalMiddle), i18n("Align Horizontal Middle")); insert(mt_Align_VerticalDistribute, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_VerticalDistribute), i18n("Align Vertical Distribute")); insert(mt_Align_HorizontalDistribute, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_HorizontalDistribute), i18n("Align Horizontal Distribute")); addMenu(alignment); } /** * Shortcut for commonly used sub menu initializations. * * @param fc The "Use Fill Color" is checked. */ void WidgetBasePopupMenu::insertSubMenuColor(bool fc) { KMenu* color = newMenu(i18nc("color menu", "Color"), this); insert(mt_Line_Color, color); insert(mt_Fill_Color, color); insert(mt_Use_Fill_Color, color, i18n("Use Fill Color"), CHECKABLE); setActionChecked(mt_Use_Fill_Color, fc); addMenu(color); } /** * Shortcut for commonly used sub menu initializations. * * @param type The widget type for which to set up the menu. */ void WidgetBasePopupMenu::insertSubMenuNew(WidgetBase::WidgetType type, KMenu *menu) { if (!menu) menu = makeNewMenu(); switch (type) { case WidgetBase::wt_Activity: insert(mt_Initial_Activity, menu); insert(mt_Activity, menu); insert(mt_End_Activity, menu); insert(mt_Final_Activity, menu); insert(mt_Branch, menu); insert(mt_Fork, menu); insert(mt_Invoke_Activity, menu); insert(mt_Param_Activity, menu); insert(mt_Activity_Transition, menu); insert(mt_Exception, menu); insert(mt_PrePostCondition, menu); insert(mt_Send_Signal, menu); insert(mt_Accept_Signal, menu); insert(mt_Accept_Time_Event, menu); insert(mt_Region, menu); insert(mt_Pin, menu); insert(mt_Object_Node, menu); break; case WidgetBase::wt_Actor: case WidgetBase::wt_UseCase: insert(mt_Actor, menu); insert(mt_UseCase, menu); break; case WidgetBase::wt_Component: insert(mt_Subsystem, menu); insert(mt_Component, menu); if (Settings::optionState().generalState.uml2) { insert(mt_Port, menu); insert(mt_InterfaceProvided, menu); insert(mt_InterfaceRequired, menu); } else { insert(mt_InterfaceComponent, menu); } insert(mt_Artifact, menu); break; case WidgetBase::wt_Class: insert(mt_Attribute, menu); insert(mt_Operation, menu); insert(mt_Template, menu); insert(mt_Class, menu); insert(mt_Interface, menu); insert(mt_Datatype, menu); insert(mt_Enum, menu); break; case WidgetBase::wt_Interface: insert(mt_Operation, menu); insert(mt_Template, menu); insert(mt_Class, menu); insert(mt_Interface, menu); insert(mt_Datatype, menu); insert(mt_Enum, menu); break; case WidgetBase::wt_Entity: insert(mt_EntityAttribute, menu); insert(mt_PrimaryKeyConstraint, menu); insert(mt_UniqueConstraint, menu); insert(mt_ForeignKeyConstraint, menu); insert(mt_CheckConstraint, menu); break; case WidgetBase::wt_Enum: insert(mt_EnumLiteral, menu); break; case WidgetBase::wt_Port: insert(mt_InterfaceProvided, menu); insert(mt_InterfaceRequired, menu); break; case WidgetBase::wt_State: insert(mt_State, menu); insert(mt_End_State, menu); insert(mt_StateTransition, menu); insert(mt_Junction, menu); insert(mt_DeepHistory, menu); insert(mt_ShallowHistory, menu); insert(mt_Choice, menu); insert(mt_StateFork, menu); insert(mt_StateJoin, menu); insert(mt_CombinedState, menu); break; default: break; } insert(mt_Note, menu); insert(mt_FloatText, menu); addMenu(menu); } void WidgetBasePopupMenu::insertSubMenuShowEntity(EntityWidget *widget) { KMenu* show = newMenu(i18n("Show"), this); show->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Show)); insert(mt_Show_Attribute_Signature, show, i18n("Attribute Signature"), CHECKABLE); setActionChecked(mt_Show_Attribute_Signature, widget->showAttributeSignature()); insert(mt_Show_Stereotypes, show, i18n("Stereotype"), CHECKABLE); setActionChecked(mt_Show_Stereotypes, widget->showStereotype()); addMenu(show); } diff --git a/umbrello/umlwidgets/statewidget.cpp b/umbrello/umlwidgets/statewidget.cpp index 2e0088ec8..b67dfc379 100644 --- a/umbrello/umlwidgets/statewidget.cpp +++ b/umbrello/umlwidgets/statewidget.cpp @@ -1,572 +1,582 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2002-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ // own header #include "statewidget.h" // app includes #include "cmds/cmdcreatediagram.h" #include "debug_utils.h" #include "dialog_utils.h" #include "docwindow.h" #include "listpopupmenu.h" #include "statedialog.h" #include "uml.h" #include "umldoc.h" #include "umlscene.h" #include "umlview.h" #include "umlwidget.h" // kde includes #include // qt includes #include /** * Creates a State widget. * * @param scene The parent of the widget. * @param stateType The type of state. * @param id The ID to assign (-1 will prompt a new ID.) */ StateWidget::StateWidget(UMLScene * scene, StateType stateType, Uml::ID::Type id) : UMLWidget(scene, WidgetBase::wt_State, id) { m_stateType = stateType; m_drawVertical = true; setAspectRatioMode(); m_Text = QLatin1String("State"); QSizeF size = minimumSize(); setSize(size.width(), size.height()); } /** * Destructor. */ StateWidget::~StateWidget() { } /** * Overrides the standard paint event. */ void StateWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); const qreal w = width(); const qreal h = height(); if (w == 0 || h == 0) return; setPenFromSettings(painter); switch (m_stateType) { case StateWidget::Normal: { if (UMLWidget::useFillColor()) { painter->setBrush(UMLWidget::fillColor()); } const QFontMetrics &fm = getFontMetrics(FT_NORMAL); const int fontHeight = fm.lineSpacing(); int textStartY = (h / 2) - (fontHeight / 2); const int count = m_Activities.count(); if (count == 0) { painter->drawRoundRect(0, 0, w, h, (h*40)/w, (w*40)/h); painter->setPen(textColor()); QFont font = UMLWidget::font(); font.setBold(false); painter->setFont(font); painter->drawText(STATE_MARGIN, textStartY, w - STATE_MARGIN * 2, fontHeight, Qt::AlignCenter, name()); setPenFromSettings(painter); } else { painter->drawRoundRect(0, 0, w, h, (h*40)/w, (w*40)/h); textStartY = STATE_MARGIN; painter->setPen(textColor()); QFont font = UMLWidget::font(); font.setBold(true); painter->setFont(font); painter->drawText(STATE_MARGIN, textStartY, w - STATE_MARGIN * 2, fontHeight, Qt::AlignCenter, name()); font.setBold(false); painter->setFont(font); setPenFromSettings(painter); int linePosY = textStartY + fontHeight; QStringList::Iterator end(m_Activities.end()); for(QStringList::Iterator it(m_Activities.begin()); it != end; ++it) { textStartY += fontHeight; painter->drawLine(0, linePosY, w, linePosY); painter->setPen(textColor()); painter->drawText(STATE_MARGIN, textStartY, w - STATE_MARGIN * 2, fontHeight, Qt::AlignCenter, *it); setPenFromSettings(painter); linePosY += fontHeight; }//end for }//end else } break; case StateWidget::Initial : painter->setBrush(WidgetBase::lineColor()); painter->drawEllipse(0, 0, w, h); break; case StateWidget::End : painter->setBrush(WidgetBase::lineColor()); painter->drawEllipse(0, 0, w, h); painter->setBrush(Qt::white); painter->drawEllipse(1, 1, w - 2, h - 2); painter->setBrush(WidgetBase::lineColor()); painter->drawEllipse(3, 3, w - 6, h - 6); break; case StateWidget::Fork: case StateWidget::Join: { painter->setPen(Qt::black); painter->setBrush(Qt::black); painter->drawRect(rect()); } break; case StateWidget::Junction: { painter->setPen(Qt::black); painter->setBrush(Qt::black); painter->drawEllipse(rect()); } break; case StateWidget::DeepHistory: { painter->setBrush(Qt::white); painter->drawEllipse(rect()); painter->setPen(Qt::black); painter->setFont(UMLWidget::font()); const QFontMetrics &fm = getFontMetrics(FT_NORMAL); const int fontHeight = fm.lineSpacing() / 2; const int xStar = fm.boundingRect(QLatin1String("H")).width(); const int yStar = fontHeight / 4; painter->drawText((w / 6), (h / 4) + fontHeight, QLatin1String("H")); painter->drawText((w / 6) + xStar, (h / 4) + fontHeight - yStar, QLatin1String("*")); } break; case StateWidget::ShallowHistory: { painter->setBrush(Qt::white); painter->drawEllipse(rect()); painter->setPen(Qt::black); painter->setFont(UMLWidget::font()); const QFontMetrics &fm = getFontMetrics(FT_NORMAL); const int fontHeight = fm.lineSpacing() / 2; painter->drawText((w / 6), (h / 4) + fontHeight, QLatin1String("H")); } break; case StateWidget::Choice: { const qreal x = w / 2; const qreal y = h / 2; QPolygonF polygon; polygon << QPointF(x, 0) << QPointF(w, y) << QPointF(x, h) << QPointF(0, y); painter->setBrush(UMLWidget::fillColor()); painter->drawPolygon(polygon); } break; case StateWidget::Combined: { const QFontMetrics &fm = getFontMetrics(FT_NORMAL); const int fontHeight = fm.lineSpacing(); painter->drawRoundedRect(rect(), 10.0, 10.0); painter->drawLine(QPointF(0, fontHeight), QPointF(w, fontHeight)); painter->setPen(textColor()); UMLView *view = m_doc->findView(m_diagramLinkId); if (view) { QFont font = UMLWidget::font(); font.setBold(false); painter->setFont(font); painter->drawText(STATE_MARGIN, 0, w - STATE_MARGIN * 2, fontHeight, Qt::AlignCenter, view->umlScene()->name()); setPenFromSettings(painter); } view->umlScene()->render(painter, rect().adjusted(2, fontHeight + 2, -2, -2)); } break; default: uWarning() << "Unknown state type: " << stateTypeStr(); break; } UMLWidget::paint(painter, option, widget); } /** * Overrides method from UMLWidget */ QSizeF StateWidget::minimumSize() const { int width = 10, height = 10; switch (m_stateType) { case StateWidget::Normal: { const QFontMetrics &fm = getFontMetrics(FT_BOLD); const int fontHeight = fm.lineSpacing(); int textWidth = fm.width(name()); const int count = m_Activities.count(); height = fontHeight; if(count > 0) { height = fontHeight * (count + 1); QStringList::ConstIterator end(m_Activities.end()); for(QStringList::ConstIterator it(m_Activities.begin()); it != end; ++it) { int w = fm.width(*it); if(w > textWidth) textWidth = w; }//end for }//end if width = textWidth > STATE_WIDTH?textWidth:STATE_WIDTH; height = height > STATE_HEIGHT?height:STATE_HEIGHT; width += STATE_MARGIN * 2; height += STATE_MARGIN * 2; break; } case StateWidget::Fork: case StateWidget::Join: if (m_drawVertical) { width = 8; height = 60; } else { width = 60; height = 8; } break; case StateWidget::Junction: width = 18; height = 18; break; case StateWidget::DeepHistory: case StateWidget::ShallowHistory: { const QFontMetrics &fm = getFontMetrics(FT_NORMAL); width = height = fm.lineSpacing(); } break; case StateWidget::Choice: width = 25; height = 25; break; case StateWidget::Combined: { height = getFontMetrics(FT_NORMAL).lineSpacing() + STATE_MARGIN; UMLView *view = m_doc->findView(m_diagramLinkId); if (view) width = getFontMetrics(FT_NORMAL).width(view->umlScene()->name()) + STATE_MARGIN * 2; } break; default: break; } return QSizeF(width, height); } /** * Overrides method from UMLWidget */ QSizeF StateWidget::maximumSize() { switch (m_stateType) { case StateWidget::Initial: case StateWidget::End: case StateWidget::Junction: case StateWidget::Choice: return QSizeF(35, 35); break; case StateWidget::DeepHistory: case StateWidget::ShallowHistory: { const QFontMetrics &fm = getFontMetrics(FT_NORMAL); const int fontHeight = fm.lineSpacing(); return QSizeF(fontHeight + 10, fontHeight + 10); } break; default: break; } return UMLWidget::maximumSize(); } /** * Set the aspect ratio mode. * Some state types have a fixed aspect ratio */ void StateWidget::setAspectRatioMode() { switch (m_stateType) { case StateWidget::Initial: case StateWidget::End: case StateWidget::Choice: case StateWidget::DeepHistory: case StateWidget::ShallowHistory: case StateWidget::Fork: case StateWidget::Join: case StateWidget::Junction: setFixedAspectRatio(true); break; default: setFixedAspectRatio(false); break; } } /** * Returns the type of state. * @return StateType */ StateWidget::StateType StateWidget::stateType() const { return m_stateType; } /** * Returns the type string of state. */ QString StateWidget::stateTypeStr() const { return QLatin1String(ENUM_NAME(StateWidget, StateType, m_stateType)); } /** * Sets the type of state. */ void StateWidget::setStateType(StateType stateType) { m_stateType = stateType; setAspectRatioMode(); } /** * Adds an activity to this widget. * @return true on success */ bool StateWidget::addActivity(const QString &activity) { m_Activities.append(activity); updateGeometry(); return true; } /** * Removes the given activity from the state. */ bool StateWidget::removeActivity(const QString &activity) { if(m_Activities.removeAll(activity) == 0) return false; updateGeometry(); return true; } /** * Renames the given activity. */ bool StateWidget::renameActivity(const QString &activity, const QString &newName) { int index = - 1; if((index = m_Activities.indexOf(activity)) == -1) return false; m_Activities[ index ] = newName; return true; } /** * Sets the states activities to the ones given. */ void StateWidget::setActivities(const QStringList &list) { m_Activities = list; updateGeometry(); } /** * Returns the list of activities. */ QStringList StateWidget::activities() const { return m_Activities; } /** * Get whether to draw a fork or join vertically. */ bool StateWidget::drawVertical() const { return m_drawVertical; } /** * Set whether to draw a fork or join vertically. */ void StateWidget::setDrawVertical(bool to) { m_drawVertical = to; setSize(height(), width()); updateGeometry(); UMLWidget::adjustAssocs(x(), y()); } /** * Show a properties dialog for a StateWidget. */ bool StateWidget::showPropertiesDialog() { bool result = false; UMLApp::app()->docWindow()->updateDocumentation(false); QPointer dialog = new StateDialog(m_scene->activeView(), this); if (dialog->exec() && dialog->getChangesMade()) { UMLApp::app()->docWindow()->showDocumentation(this, true); UMLApp::app()->document()->setModified(true); result = true; } delete dialog; return result; } Uml::ID::Type StateWidget::diagramLink() { return m_diagramLinkId; } void StateWidget::setDiagramLink(const Uml::ID::Type &id) { m_diagramLinkId = id; } /** * Creates the "statewidget" XMI element. */ void StateWidget::saveToXMI1(QDomDocument & qDoc, QDomElement & qElement) { QDomElement stateElement = qDoc.createElement(QLatin1String("statewidget")); UMLWidget::saveToXMI1(qDoc, stateElement); stateElement.setAttribute(QLatin1String("statename"), m_Text); stateElement.setAttribute(QLatin1String("documentation"), m_Doc); stateElement.setAttribute(QLatin1String("statetype"), m_stateType); if (m_stateType == Fork || m_stateType == Join) stateElement.setAttribute(QLatin1String("drawvertical"), m_drawVertical); if (m_stateType == Combined) stateElement.setAttribute(QLatin1String("diagramlinkid"), Uml::ID::toString(m_diagramLinkId)); //save states activities QDomElement activitiesElement = qDoc.createElement(QLatin1String("Activities")); QStringList::Iterator end(m_Activities.end()); for(QStringList::Iterator it(m_Activities.begin()); it != end; ++it) { QDomElement tempElement = qDoc.createElement(QLatin1String("Activity")); tempElement.setAttribute(QLatin1String("name"), *it); activitiesElement.appendChild(tempElement); }//end for stateElement.appendChild(activitiesElement); qElement.appendChild(stateElement); } /** * Loads a "statewidget" XMI element. */ bool StateWidget::loadFromXMI1(QDomElement & qElement) { if(!UMLWidget::loadFromXMI1(qElement)) return false; m_Text = qElement.attribute(QLatin1String("statename")); m_Doc = qElement.attribute(QLatin1String("documentation")); QString type = qElement.attribute(QLatin1String("statetype"), QLatin1String("1")); m_stateType = (StateType)type.toInt(); if (m_stateType == Combined) { QString linkID = qElement.attribute(QLatin1String("diagramlinkid")); m_diagramLinkId = Uml::ID::fromString(linkID); } setAspectRatioMode(); QString drawVertical = qElement.attribute(QLatin1String("drawvertical"), QLatin1String("1")); m_drawVertical = (bool)drawVertical.toInt(); //load states activities QDomNode node = qElement.firstChild(); QDomElement tempElement = node.toElement(); if(!tempElement.isNull() && tempElement.tagName() == QLatin1String("Activities")) { QDomNode node = tempElement.firstChild(); QDomElement activityElement = node.toElement(); while(!activityElement.isNull()) { if(activityElement.tagName() == QLatin1String("Activity")) { QString name = activityElement.attribute(QLatin1String("name")); if(!name.isEmpty()) m_Activities.append(name); }//end if node = node.nextSibling(); activityElement = node.toElement(); }//end while }//end if return true; } /** * Captures any popup menu signals for menus it created. */ void StateWidget::slotMenuSelection(QAction* action) { bool ok = false; QString nameNew = name(); ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action); switch(sel) { case ListPopupMenu::mt_Rename: nameNew = name(); ok = Dialog_Utils::askNewName(WidgetBase::WidgetType::wt_State, nameNew); if (ok && nameNew.length() > 0) { setName(nameNew); } break; case ListPopupMenu::mt_Properties: showPropertiesDialog(); break; case ListPopupMenu::mt_New_Activity: nameNew = i18n("new activity"); ok = Dialog_Utils::askName(i18n("Enter Activity"), i18n("Enter the name of the new activity:"), nameNew); if (ok && nameNew.length() > 0) { addActivity(nameNew); } break; case ListPopupMenu::mt_FlipHorizontal: setDrawVertical(false); break; case ListPopupMenu::mt_FlipVertical: setDrawVertical(true); break; - case ListPopupMenu::mt_CombinedState: { - QString diagramName = m_doc->createDiagramName(Uml::DiagramType::State); - Uml::CmdCreateDiagram* d = new Uml::CmdCreateDiagram(m_doc, Uml::DiagramType::State, diagramName); - UMLApp::app()->executeCommand(d); - m_diagramLinkId = d->view()->umlScene()->ID(); - setStateType(Combined); + + case ListPopupMenu::mt_CombinedState: + { + QString diagramName = m_doc->createDiagramName(Uml::DiagramType::State); + Uml::CmdCreateDiagram* d = new Uml::CmdCreateDiagram(m_doc, Uml::DiagramType::State, diagramName); + UMLApp::app()->executeCommand(d); + m_diagramLinkId = d->view()->umlScene()->ID(); + setStateType(Combined); + } + break; + + case ListPopupMenu::mt_EditCombinedState: + if (m_diagramLinkId.empty()) { + uError() << "no diagram id defined at widget '" << Uml::ID::toString(id()) << "'"; + break; + } + UMLApp::app()->document()->changeCurrentView(m_diagramLinkId); break; - } default: UMLWidget::slotMenuSelection(action); break; } }