diff --git a/umbrello/icon_utils.cpp b/umbrello/icon_utils.cpp index 6f85d8a88..191bb526f 100644 --- a/umbrello/icon_utils.cpp +++ b/umbrello/icon_utils.cpp @@ -1,394 +1,395 @@ /* Copyright 2008 Andreas Fischer Copyright (C) 2009-2014 * Umbrello UML Modeller Authors * 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) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "icon_utils.h" #include "basictypes.h" #include "debug_utils.h" #include "optionstate.h" #include #include namespace Icon_Utils { #define ICON_PREFIX QLatin1String(":/pics/") /** * Returns the pixmap for the given type as small icon. * @param type the identification of the icon * @return the wanted pixmap */ QPixmap SmallIcon(IconType type) { QString icon = toString(type); if (QFile::exists(ICON_PREFIX + icon + QLatin1String(".png"))) return QPixmap(ICON_PREFIX + icon); else return SmallIcon(icon); } /** * Returns the pixmap for the given type as bar icon. * @param type the identification of the icon * @return the wanted pixmap */ QPixmap BarIcon(IconType type) { QString icon = toString(type); if (QFile::exists(ICON_PREFIX + icon + QLatin1String(".png"))) return QPixmap(ICON_PREFIX + icon); else return BarIcon(icon); } /** * Returns the pixmap for the given type as main bar icon. * @param type the identification of the icon * @return the wanted pixmap */ QPixmap MainBarIcon(IconType type) { QString icon = toString(type); if (QFile::exists(ICON_PREFIX + icon + QLatin1String(".png"))) return QPixmap(ICON_PREFIX + icon); else return MainBarIcon(icon); } /** * Returns the pixmap for the given type as user icon. * @param type the identification of the icon * @return the wanted pixmap */ QPixmap UserIcon(IconType type) { QString icon = toString(type); if (QFile::exists(ICON_PREFIX + icon + QLatin1String(".png"))) return QPixmap(ICON_PREFIX + icon); else return UserIcon(icon); } /** * Returns the pixmap for the given type as desktop icon. * @param type the identification of the icon * @return the wanted icon */ QPixmap DesktopIcon(IconType type) { QString icon = toString(type); if (QFile::exists(ICON_PREFIX + icon + QLatin1String(".png"))) return QPixmap(ICON_PREFIX + icon); else return DesktopIcon(icon); } /** * Returns the pixmap for the given type as user icon. * This is used in worktoolbar to create cursors. * @param type the identification of the icon * @return the wanted cursor */ QCursor Cursor(IconType type) { // TODO: generate from a 32x32 cursor template and place requested icon into QString icon = QLatin1String("cursor-") + toString(type); if (QFile::exists(ICON_PREFIX + icon + QLatin1String(".png"))) return QCursor(QPixmap(ICON_PREFIX + icon), 9, 9); else return QCursor(UserIcon(icon), 9, 9); } /** * Return the icon corresponding to the given Diagram_Type. * @param dt the diagram type * @return the wanted icon */ QPixmap iconSet(Uml::DiagramType::Enum dt) { switch (dt) { case Uml::DiagramType::UseCase: return DesktopIcon(it_Diagram_Usecase); case Uml::DiagramType::Collaboration: return DesktopIcon(it_Diagram_Collaboration); case Uml::DiagramType::Class: return DesktopIcon(it_Diagram_Class); case Uml::DiagramType::Object: return DesktopIcon(it_Diagram_Object); case Uml::DiagramType::Sequence: return DesktopIcon(it_Diagram_Sequence); case Uml::DiagramType::State: return DesktopIcon(it_Diagram_State); case Uml::DiagramType::Activity: return DesktopIcon(it_Diagram_Activity); case Uml::DiagramType::Component: return DesktopIcon(it_Diagram_Component); case Uml::DiagramType::Deployment: return DesktopIcon(it_Diagram_Deployment); case Uml::DiagramType::EntityRelationship: return DesktopIcon(it_Diagram_EntityRelationship); default: uDebug() << "Widget_Utils::iconSet: unknown diagram type " << Uml::DiagramType::toString(dt); return QPixmap(); } } /** * Return the icon corresponding to the given Diagram_Type. * @param dt the diagram type * @return the wanted icon */ QPixmap smallIcon(Uml::DiagramType::Enum dt) { switch (dt) { case Uml::DiagramType::UseCase: return SmallIcon(it_Diagram_Usecase); case Uml::DiagramType::Collaboration: return SmallIcon(it_Diagram_Collaboration); case Uml::DiagramType::Class: return SmallIcon(it_Diagram_Class); case Uml::DiagramType::Object: return SmallIcon(it_Diagram_Object); case Uml::DiagramType::Sequence: return SmallIcon(it_Diagram_Sequence); case Uml::DiagramType::State: return SmallIcon(it_Diagram_State); case Uml::DiagramType::Activity: return SmallIcon(it_Diagram_Activity); case Uml::DiagramType::Component: return SmallIcon(it_Diagram_Component); case Uml::DiagramType::Deployment: return SmallIcon(it_Diagram_Deployment); case Uml::DiagramType::EntityRelationship: return SmallIcon(it_Diagram_EntityRelationship); default: uDebug() << "Widget_Utils::smallIcon: unknown diagram type " << Uml::DiagramType::toString(dt); return QPixmap(); } } /** * Conversion from icon type to its string name. * @param type the identification of the icon * @return the string representation of the type */ QString toString(IconType type) { switch (type) { case it_Accept_Signal: return QLatin1String("accept_signal"); case it_Accept_TimeEvent: return QLatin1String("accept_time_event"); case it_Activity: return QLatin1String("activity"); case it_Activity_End: return QLatin1String("end_state"); case it_Activity_Final: return QLatin1String("final_activity"); case it_Activity_Initial: return QLatin1String("initial_state"); case it_Activity_Transition: return QLatin1String("uniassociation"); case it_Actor: return QLatin1String("actor"); case it_Add_Point: return QLatin1String("format-add-node"); case it_Aggregation: return QLatin1String("aggregation"); case it_Align_Bottom: return QLatin1String("align-vertical-bottom"); case it_Align_HorizontalDistribute: return QLatin1String("distribute-horizontal"); case it_Align_HorizontalMiddle: return QLatin1String("align-horizontal-center"); case it_Align_Left: return QLatin1String("align-horizontal-left"); case it_Align_Right: return QLatin1String("align-horizontal-right"); case it_Align_Top: return QLatin1String("align-vertical-top"); case it_Align_VerticalDistribute: return QLatin1String("distribute-vertical"); case it_Align_VerticalMiddle: return QLatin1String("align-vertical-center"); case it_Anchor: return QLatin1String("anchor"); case it_And_Line: return QLatin1String("andline"); case it_Arrow: return QLatin1String("arrow"); case it_Arrow_Down: return QLatin1String("arrow-down"); case it_Arrow_Up: return QLatin1String("arrow-up"); case it_Artifact: return QLatin1String("artifact"); case it_Association: return QLatin1String("association"); case it_Attribute_New: return QLatin1String("CVpublic_var"); case it_Box: return QLatin1String("box"); case it_Branch: return QLatin1String("branch"); case it_Category: return QLatin1String("category"); case it_Category_Child: return QLatin1String("child2category"); case it_Category_Parent: return QLatin1String("category2parent"); case it_Change_Font: return QLatin1String("preferences-desktop-font"); case it_Check_Constraint: return QLatin1String("check_constraint"); case it_Choice_Rhomb: return QLatin1String("choice-rhomb"); case it_Choice_Round: return QLatin1String("choice-round"); case it_Class: return QLatin1String("class"); case it_ClassOrPackage: return QLatin1String("class-or-package"); case it_Clear: return QLatin1String("edit-clear"); case it_Code_Gen_Wizard: return QLatin1String("umbrello"); case it_Color_Fill: return QLatin1String("fill-color"); case it_Color_Line: return QLatin1String("draw-brush"); case it_Combined_Fragment: return QLatin1String("combined_fragment"); case it_Component: return Settings::optionState().generalState.uml2 ? QLatin1String("component") : QLatin1String("component1"); case it_Composition: return QLatin1String("composition"); case it_Condition_PrePost: return QLatin1String("PrePostCondition"); case it_Constraint_Check: return QLatin1String("check_constraint"); case it_Constraint_ForeignKey: return QLatin1String("foreignkey_constraint"); case it_Constraint_PrimaryKey: return QLatin1String("primarykey_constraint"); case it_Constraint_Unique: return QLatin1String("unique_constraint"); case it_Containment: return QLatin1String("containment"); case it_Copy: return QLatin1String("edit-copy"); case it_Cut: return QLatin1String("edit-cut"); case it_Datatype: return QLatin1String("datatype"); case it_Delete: return QLatin1String("edit-delete"); case it_Delete_Point: return QLatin1String("format-remove-node"); case it_Dependency: return QLatin1String("dependency"); case it_Diagram: return QLatin1String("CVnamespace"); case it_Diagram_Activity: return QLatin1String("umbrello_diagram_activity"); case it_Diagram_Class: return QLatin1String("umbrello_diagram_class"); case it_Diagram_Collaboration: return QLatin1String("umbrello_diagram_collaboration"); case it_Diagram_Component: return QLatin1String("umbrello_diagram_component"); case it_Diagram_Deployment: return QLatin1String("umbrello_diagram_deployment"); case it_Diagram_EntityRelationship: return QLatin1String("umbrello_diagram_deployment"); case it_Diagram_Object: return QLatin1String("umbrello_diagram_object"); case it_Diagram_Sequence: return QLatin1String("umbrello_diagram_sequence"); case it_Diagram_State: return QLatin1String("umbrello_diagram_state"); case it_Diagram_Usecase: return QLatin1String("umbrello_diagram_usecase"); case it_Directional_Association: return QLatin1String("uniassociation"); case it_Document_Edit: return QLatin1String("document-edit"); case it_Duplicate: return QLatin1String("duplicate"); case it_EndState: return QLatin1String("end_state"); case it_Entity: return QLatin1String("entity"); case it_Entity_Attribute: return QLatin1String("text-x-generic"); case it_Entity_Attribute_New: return QLatin1String("text-x-generic"); case it_Enum: return QLatin1String("enum"); case it_Enum_Literal: return QLatin1String("text-x-generic"); case it_Exception: return QLatin1String("exception"); case it_Export_Files: return QLatin1String("document-export"); case it_Export_Picture: return QLatin1String("image-x-generic"); + case it_File_Open: return QLatin1String("document-open"); case it_Folder: return QLatin1String("folder-new"); case it_Folder_Cyan: return QLatin1String("folder"); case it_Folder_Cyan_Open: return QLatin1String("folder-open"); case it_Folder_Green: return QLatin1String("folder-green"); case it_Folder_Green_Open: return QLatin1String("folder-green"); //FIXME was folder_green_open case it_Folder_Grey: return QLatin1String("folder-grey"); case it_Folder_Grey_Open: return QLatin1String("folder-grey"); //FIXME was folder_grey_open case it_Folder_Orange: return QLatin1String("folder-orange"); case it_Folder_Orange_Open: return QLatin1String("folder-orange"); //FIXME was folder_orange_open case it_Folder_Red: return QLatin1String("folder-red"); case it_Folder_Red_Open: return QLatin1String("folder-red"); //FIXME was folder_red_open case it_Folder_Violet: return QLatin1String("folder-violet"); case it_Folder_Violet_Open: return QLatin1String("folder-violet"); //FIXME was folder_violet_open case it_ForeignKey_Constraint: return QLatin1String("foreignkey_constraint"); case it_Fork_Join: return QLatin1String("activity-fork"); case it_Fork_State: return QLatin1String("state-fork"); case it_Generalisation: return QLatin1String("generalisation"); case it_Go_Next: return QLatin1String("go-next"); case it_Go_Previous: return QLatin1String("go-previous"); case it_History_Deep: return QLatin1String("deep-history"); case it_History_Shallow: return QLatin1String("shallow-history"); case it_Home: return QLatin1String("user-home"); case it_Implementation_Attribute: return QLatin1String("CVimplementation_var"); case it_Implementation_Method: return QLatin1String("CVimplementation_meth"); case it_Implements: return QLatin1String("generalisation"); case it_Import_File: return QLatin1String("document-import"); case it_Import_Files: return QLatin1String("document-import"); case it_Import_Project: return QLatin1String("document-import"); case it_InitialState: return QLatin1String("initial_state"); case it_Instance: return QLatin1String("instance"); case it_Interface: return QLatin1String("interface"); case it_Interface_Requirement: return QLatin1String("interface-requirement"); case it_Interface_Provider: return QLatin1String("interface-provider"); case it_Join: return QLatin1String("join"); case it_Junction: return QLatin1String("junction"); case it_Literal_New: return QLatin1String("text-x-generic"); case it_Message_Async: return QLatin1String("umbr-message-asynchronous"); case it_Message_Asynchronous: return QLatin1String("umbr-coll-message-asynchronous"); case it_Message_Found: return QLatin1String("umbr-message-found"); case it_Message_Lost: return QLatin1String("umbr-message-lost"); case it_Message_Sync: return QLatin1String("umbr-message-synchronous"); case it_Message_Synchronous: return QLatin1String("umbr-coll-message-synchronous"); case it_New: return QLatin1String("document-new"); case it_Node: return QLatin1String("node"); case it_Note: return QLatin1String("note"); case it_Object: return QLatin1String("object"); case it_Object_Node: return QLatin1String("object_node"); case it_Operation_New: return QLatin1String("document-new"); case it_Operation_Public_New: return QLatin1String("CVpublic_meth"); case it_Package: return QLatin1String("package"); case it_Parameter_New: return QLatin1String("text-x-generic"); case it_Paste: return QLatin1String("edit-paste"); case it_Pin: return QLatin1String("pin"); case it_Port: return QLatin1String("port"); case it_Precondition: return QLatin1String("precondition"); case it_PrimaryKey_Constraint: return QLatin1String("primarykey_constraint"); case it_Private_Attribute: return QLatin1String("CVprivate_var"); case it_Private_Method: return QLatin1String("CVprivate_meth"); case it_Properties: return QLatin1String("preferences-system"); case it_Properties_Activities: return QLatin1String("text-x-generic"); case it_Properties_Associations: return QLatin1String("preferences-other"); case it_Properties_Attributes: return QLatin1String("preferences-other"); case it_Properties_AutoLayout: return QLatin1String("code-class"); case it_Properties_Class: return QLatin1String("document-properties"); case it_Properties_CodeGeneration: return QLatin1String("document-export"); case it_Properties_CodeImport: return QLatin1String("document-import"); case it_Properties_CodeViewer: return QLatin1String("package_graphics_viewer"); case it_Properties_Color: return QLatin1String("preferences-desktop-color"); case it_Properties_Columns: return QLatin1String("preferences-other"); case it_Properties_Contents: return QLatin1String("preferences-other"); case it_Properties_Display: return QLatin1String("preferences-desktop-theme"); case it_Properties_EntityAttributes: return QLatin1String("preferences-other"); case it_Properties_EntityConstraints: return QLatin1String("preferences-other"); case it_Properties_EnumLiterals: return QLatin1String("preferences-other"); case it_Properties_Font: return QLatin1String("preferences-desktop-font"); case it_Properties_General: return QLatin1String("preferences-other"); case it_Properties_Operations: return QLatin1String("preferences-other"); case it_Properties_Roles: return QLatin1String("preferences-other"); case it_Properties_Templates: return QLatin1String("preferences-other"); case it_Properties_UserInterface: return QLatin1String("preferences-desktop-theme"); case it_Protected_Attribute: return QLatin1String("CVprotected_var"); case it_Protected_Method: return QLatin1String("CVprotected_meth"); case it_Public_Attribute: return QLatin1String("CVpublic_var"); case it_Public_Method: return QLatin1String("CVpublic_meth"); case it_Redo: return QLatin1String("edit-redo"); case it_Refactor: return QLatin1String("refactor"); case it_Region: return QLatin1String("region"); case it_Relationship: return QLatin1String("relationship"); case it_Remove: return QLatin1String("remove"); case it_Rename: return QLatin1String("edit-rename"); case it_Send_Signal: return QLatin1String("send_signal"); case it_Show: return QLatin1String("document-preview"); case it_State: return QLatin1String("state"); case it_State_Activity: return QLatin1String("text-x-generic"); case it_State_Transition: return QLatin1String("uniassociation"); case it_Subsystem: return QLatin1String("subsystem"); case it_Tab_Close: return QLatin1String("tab-close"); case it_Tab_New: return QLatin1String("tab-new"); case it_Template: return QLatin1String("template"); case it_Template_Class: return QLatin1String("format-justify-fill"); case it_Template_Interface: return QLatin1String("text-x-generic-template"); case it_Template_New: return QLatin1String("text-x-generic-template"); case it_Text: return QLatin1String("text"); case it_Undo: return QLatin1String("edit-undo"); case it_UndoView: return QLatin1String("document-save"); case it_Uniassociation: return QLatin1String("uniassociation"); case it_Unique_Constraint: return QLatin1String("unique_constraint"); case it_UseCase: return QLatin1String("usecase"); case it_View_Code: return QLatin1String("text-x-generic"); case it_Zoom_100: return QLatin1String("zoom-original"); case it_Zoom_Slider: return QLatin1String("zoom-original"); default: return QString(); } } } // namespace diff --git a/umbrello/icon_utils.h b/umbrello/icon_utils.h index 84b1c24ae..d8d4ed7cf 100644 --- a/umbrello/icon_utils.h +++ b/umbrello/icon_utils.h @@ -1,257 +1,258 @@ /* Copyright 2008 Andreas Fischer 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) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ICON_UTILS_H #define ICON_UTILS_H // app includes #include "basictypes.h" // kde includes #if QT_VERSION < 0x050000 #include #endif // qt includes #include #if QT_VERSION >= 0x050000 #include #endif #include /** * This class is a gateway to KIconLoader for for handling all the * used icons in umbrello. Identification is done with an enum and * then a translation to the icon name. * @author Andreas Fischer */ namespace Icon_Utils { enum IconType { it_Home = 0, it_Arrow, + it_File_Open, it_Folder, it_Folder_Cyan, it_Folder_Cyan_Open, it_Folder_Green, it_Folder_Green_Open, it_Folder_Grey, it_Folder_Grey_Open, it_Folder_Red, it_Folder_Red_Open, it_Folder_Violet, it_Folder_Violet_Open, it_Folder_Orange, it_Folder_Orange_Open, it_Properties_General, it_Properties_Color, it_Properties_Display, it_Properties_Attributes, it_Properties_Operations, it_Properties_Templates, it_Properties_EnumLiterals, it_Properties_EntityAttributes, it_Properties_EntityConstraints, it_Properties_Contents, it_Properties_Associations, it_Properties_Font, it_Properties_Activities, it_Properties_Roles, it_Properties_UserInterface, it_Properties_Class, it_Properties_CodeImport, it_Properties_CodeGeneration, it_Properties_CodeViewer, it_Properties_Columns, it_Diagram, //change to have different one for each type of diagram it_Class, it_Object, it_Template, it_Template_Class, it_Template_Interface, it_Package, it_Subsystem, it_Component, it_Port, it_Node, it_Artifact, it_Interface, it_Interface_Provider, it_Interface_Requirement, it_Datatype, it_Enum, it_Entity, it_Actor, it_UseCase, it_Generalisation, it_Association, it_Uniassociation, it_Text, it_Note, it_Box, it_Anchor, it_Containment, it_Public_Method, it_Private_Method, it_Protected_Method, it_Implementation_Method, it_Public_Attribute, it_Private_Attribute, it_Protected_Attribute, it_Implementation_Attribute, it_Unique_Constraint, it_PrimaryKey_Constraint, it_ForeignKey_Constraint, it_Check_Constraint, it_Diagram_Activity, it_Diagram_Class, it_Diagram_Collaboration, it_Diagram_Component, it_Diagram_Deployment, it_Diagram_EntityRelationship, it_Diagram_Sequence, it_Diagram_State, it_Diagram_Usecase, it_Diagram_Object, it_New, it_Delete, it_Add_Point, it_Delete_Point, it_Rename, it_Cut, it_Copy, it_Paste, it_Undo, it_Redo, it_UndoView, it_Go_Next, it_Go_Previous, it_Properties, it_Show, it_Refactor, it_View_Code, it_Tab_New, it_Tab_Close, it_Change_Font, it_Arrow_Up, it_Arrow_Down, it_Clear, it_Operation_New, it_Operation_Public_New, it_Attribute_New, it_Template_New, it_Literal_New, it_Entity_Attribute_New, it_Parameter_New, it_Color_Line, it_Color_Fill, it_Import_File, it_Import_Project, it_Import_Files, it_Export_Files, it_Export_Picture, it_InitialState, it_EndState, it_Branch, it_Entity_Attribute, it_Constraint_PrimaryKey, it_Constraint_ForeignKey, it_Constraint_Check, it_Constraint_Unique, it_Enum_Literal, it_State_Activity, it_Message_Sync, it_Message_Async, it_Message_Found, it_Message_Lost, it_Combined_Fragment, it_Precondition, it_Dependency, it_Aggregation, it_Relationship, it_Directional_Association, it_Implements, it_Composition, it_Region, it_Send_Signal, it_Accept_Signal, it_Accept_TimeEvent, it_Fork_Join, it_History_Deep, it_History_Shallow, it_Join, it_Fork_State, it_Junction, it_Choice_Round, it_Choice_Rhomb, it_And_Line, it_State_Transition, it_Activity_Transition, it_Activity, it_State, it_Activity_End, it_Activity_Final, it_Pin, it_Activity_Initial, it_Message_Synchronous, it_Message_Asynchronous, it_Exception, it_Object_Node, it_Condition_PrePost, it_Category, it_Category_Parent, it_Category_Child, it_Zoom_Slider, it_Zoom_100, it_Align_Right, it_Align_Left, it_Align_Top, it_Align_Bottom, it_Align_VerticalMiddle, it_Align_HorizontalMiddle, it_Align_VerticalDistribute, it_Align_HorizontalDistribute, it_Code_Gen_Wizard, it_Properties_AutoLayout, it_Document_Edit, it_ClassOrPackage, it_Instance, it_Remove, it_Duplicate, N_ICONTYPES // must remain last }; QPixmap SmallIcon(IconType type); QPixmap BarIcon(IconType type); QPixmap MainBarIcon(IconType type); QPixmap UserIcon(IconType type); QPixmap DesktopIcon(IconType type); QCursor Cursor(IconType type); QString toString(IconType type); QPixmap iconSet(Uml::DiagramType::Enum dt); QPixmap smallIcon(Uml::DiagramType::Enum dt); } // namespace #endif // ICONCONTAINER_H diff --git a/umbrello/menus/listpopupmenu.cpp b/umbrello/menus/listpopupmenu.cpp index ba730131d..7262addcc 100644 --- a/umbrello/menus/listpopupmenu.cpp +++ b/umbrello/menus/listpopupmenu.cpp @@ -1,628 +1,629 @@ /*************************************************************************** * 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_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 497c6a320..bee7ac6b3 100644 --- a/umbrello/menus/listpopupmenu.h +++ b/umbrello/menus/listpopupmenu.h @@ -1,310 +1,311 @@ /*************************************************************************** * 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_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/umllistviewpopupmenu.cpp b/umbrello/menus/umllistviewpopupmenu.cpp index 8343d343b..df63c87cf 100644 --- a/umbrello/menus/umllistviewpopupmenu.cpp +++ b/umbrello/menus/umllistviewpopupmenu.cpp @@ -1,420 +1,426 @@ /*************************************************************************** * 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 "umllistviewpopupmenu.h" #include "debug_utils.h" #include "folder.h" #include "optionstate.h" #include "model_utils.h" // kde includes #include UMLListViewPopupMenu::UMLListViewPopupMenu(QWidget *parent, UMLListViewItem *item) : ListPopupMenu(parent) { UMLObject *object = item->umlObject(); UMLListViewItem::ListViewType type = item->type(); switch(type) { case UMLListViewItem::lvt_Logical_View: insertContainerItems(true); addSeparator(); insert(mt_Paste); addSeparator(); insert(mt_Import_Project); insert(mt_Import_Class); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Component_View: insertSubMenuNew(type); addSeparator(); insert(mt_Paste); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Deployment_View: insertSubMenuNew(type); addSeparator(); insert(mt_Paste); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_EntityRelationship_Model: insertSubMenuNew(type); addSeparator(); insert(mt_Paste); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_UseCase_View: insertSubMenuNew(type); addSeparator(); // insert(mt_Cut); // insert(mt_Copy); insert(mt_Paste); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Logical_Folder: insertContainerItems(true); insertStdItems(); insert(mt_Import_Project); insertSubmodelAction(); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Datatype_Folder: insertSubMenuNew(type); insertStdItems(); insertSubmodelAction(); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Component_Folder: insertSubMenuNew(type); insertStdItems(); insertSubmodelAction(); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Deployment_Folder: insertSubMenuNew(type); insertStdItems(); insertSubmodelAction(); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_UseCase_Folder: insertSubMenuNew(type); insertStdItems(); insertSubmodelAction(); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_EntityRelationship_Folder: insertSubMenuNew(type); insertStdItems(); insertSubmodelAction(); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_UseCase_Diagram: case UMLListViewItem::lvt_Sequence_Diagram: case UMLListViewItem::lvt_Class_Diagram: case UMLListViewItem::lvt_Object_Diagram: case UMLListViewItem::lvt_Collaboration_Diagram: case UMLListViewItem::lvt_State_Diagram: case UMLListViewItem::lvt_Activity_Diagram: case UMLListViewItem::lvt_Component_Diagram: case UMLListViewItem::lvt_Deployment_Diagram: case UMLListViewItem::lvt_EntityRelationship_Diagram: insertStdItems(false); insert(mt_Clone); insert(mt_Export_Image); insert(mt_Properties); break; + case UMLListViewItem::lvt_Artifact: + insert(mt_Open_File); + insertStdItems(true); + insert(mt_Show); + insert(mt_Properties); + break; + case UMLListViewItem::lvt_Class: insertSubMenuNew(type); insertStdItems(); insert(mt_Show); addSeparator(); if (object && object->stereotype() == QLatin1String("class-or-package")) { insert(mt_ChangeToClass, i18n("Change into Class")); insert(mt_ChangeToPackage, i18n("Change into Package")); } addSeparator(); insert(mt_Properties); break; case UMLListViewItem::lvt_Package: insertContainerItems(false); insertStdItems(); insert(mt_Show); insert(mt_Properties); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Subsystem: insertSubMenuNew(type); insertStdItems(); insert(mt_Show); insert(mt_Properties); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Component: insertSubMenuNew(type); insertStdItems(); insert(mt_Show); insert(mt_Properties); addSeparator(); insert(mt_Expand_All); insert(mt_Collapse_All); break; case UMLListViewItem::lvt_Datatype: case UMLListViewItem::lvt_EnumLiteral: case UMLListViewItem::lvt_Port: case UMLListViewItem::lvt_Node: case UMLListViewItem::lvt_Actor: - case UMLListViewItem::lvt_Artifact: case UMLListViewItem::lvt_UseCase: case UMLListViewItem::lvt_Attribute: case UMLListViewItem::lvt_EntityAttribute: case UMLListViewItem::lvt_InstanteAttribute: case UMLListViewItem::lvt_Operation: case UMLListViewItem::lvt_Template: insertStdItems(false); insert(mt_Show); insert(mt_Properties); break; case UMLListViewItem::lvt_Interface: insertSubMenuNew(type); insertStdItems(); insert(mt_Show); insert(mt_Properties); break; case UMLListViewItem::lvt_Enum: insertSubMenuNew(type); insertStdItems(); insert(mt_Show); insert(mt_Properties); break; case UMLListViewItem::lvt_Category: insertSubMenuCategoryType(object->asUMLCategory()); insertStdItems(false); insert(mt_Show); insert(mt_Properties); break; case UMLListViewItem::lvt_Entity: insertSubMenuNew(type); insertStdItems(); insert(mt_Show); insert(mt_Properties); break; case UMLListViewItem::lvt_Instance: insertSubMenuNew(type); insertStdItems(); insert(mt_Show); insert(mt_Properties); break; case UMLListViewItem::lvt_UniqueConstraint: case UMLListViewItem::lvt_PrimaryKeyConstraint: case UMLListViewItem::lvt_ForeignKeyConstraint: case UMLListViewItem::lvt_CheckConstraint: insert(mt_Rename); insert(mt_Delete); insert(mt_Show); insert(mt_Properties); break; case UMLListViewItem::lvt_Model: insert(mt_Model, i18n("Rename...")); break; case UMLListViewItem::lvt_Properties: insert(mt_Expand_All); insert(mt_Collapse_All); insert(mt_Properties); break; case UMLListViewItem::lvt_Properties_AutoLayout: case UMLListViewItem::lvt_Properties_Class: case UMLListViewItem::lvt_Properties_CodeImport: case UMLListViewItem::lvt_Properties_CodeGeneration: case UMLListViewItem::lvt_Properties_CodeViewer: case UMLListViewItem::lvt_Properties_Font: case UMLListViewItem::lvt_Properties_General: case UMLListViewItem::lvt_Properties_UserInterface: insert(mt_Properties); break; #ifndef CHECK_SWITCH default: break; #endif } setupActionsData(); } /** * Override of related method from class ListPopupMenu * @param type list view type * @param menu pointer to menu instance or 0 to create a new instance */ void UMLListViewPopupMenu::insertSubMenuNew(UMLListViewItem::ListViewType type, KMenu *menu) { if (!menu) { menu = makeNewMenu(); } switch(type) { case UMLListViewItem::lvt_Deployment_View: insert(mt_Deployment_Folder, menu); insert(mt_Node, menu); insert(mt_Deployment_Diagram, menu); break; case UMLListViewItem::lvt_EntityRelationship_Model: insert(mt_EntityRelationship_Folder, menu); insert(mt_Entity, menu); insert(mt_Category, menu); insert(mt_EntityRelationship_Diagram, menu); break; case UMLListViewItem::lvt_UseCase_View: insert(mt_UseCase_Folder, menu); insert(mt_Actor, menu); insert(mt_UseCase, menu); insert(mt_UseCase_Diagram, menu); break; case UMLListViewItem::lvt_Component_View: case UMLListViewItem::lvt_Component_Folder: insert(mt_Component_Folder, menu); insert(mt_Subsystem, menu); insert(mt_Component, menu); insert(mt_Artifact, menu); insert(mt_Component_Diagram, menu); break; case UMLListViewItem::lvt_Datatype_Folder: insert(mt_Datatype, menu); break; case UMLListViewItem::lvt_Deployment_Folder: insert(mt_Deployment_Folder, menu); insert(mt_Node, menu); insert(mt_Deployment_Diagram, menu); break; case UMLListViewItem::lvt_UseCase_Folder: insert(mt_UseCase_Folder, menu); insert(mt_Actor, menu); insert(mt_UseCase, menu); insert(mt_UseCase_Diagram, menu); break; case UMLListViewItem::lvt_EntityRelationship_Folder: insert(mt_EntityRelationship_Folder, menu); insert(mt_Entity, menu); insert(mt_EntityRelationship_Diagram, menu); break; case UMLListViewItem::lvt_Class: insert(mt_Attribute, menu); insert(mt_Operation, menu); insert(mt_Template, menu); insertContainerItems(menu, false, false); break; case UMLListViewItem::lvt_Component: insert(mt_Component, menu); if (Settings::optionState().generalState.uml2) insert(mt_Port, menu); insert(mt_Artifact, menu); break; case UMLListViewItem::lvt_Interface: insert(mt_Operation, menu); insert(mt_Template, menu); insertContainerItems(menu, false, false); break; case UMLListViewItem::lvt_Entity: insert(mt_EntityAttribute, menu); insert(mt_PrimaryKeyConstraint, menu); insert(mt_UniqueConstraint, menu); insert(mt_ForeignKeyConstraint, menu); insert(mt_CheckConstraint, menu); break; case UMLListViewItem::lvt_Enum: insert(mt_EnumLiteral, menu); break; //case UMLListViewItem::lvt_Object: // break; case UMLListViewItem::lvt_Subsystem: insert(mt_Subsystem, menu); insert(mt_Component, menu); insert(mt_Artifact, menu); break; default: delete menu; return; } addMenu(menu); } void UMLListViewPopupMenu::insertStdItems(bool insertLeadingSeparator) { if (insertLeadingSeparator) addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); addSeparator(); insert(mt_Delete); } /** * Inserts a menu item for externalization/de-externalization * of a folder. */ void UMLListViewPopupMenu::insertSubmodelAction() { const Settings::OptionState& ostat = Settings::optionState(); if (ostat.generalState.tabdiagrams) { // Umbrello currently does not support External Folders // in combination with Tabbed Diagrams. // If you need external folders then disable the tabbed diagrams // in the General Settings. return; } UMLObject *o = Model_Utils::treeViewGetCurrentObject(); if (o == 0) { uError() << " Model_Utils::treeViewGetCurrentObject() returns NULL"; return; } UMLFolder *f = o->asUMLFolder(); if (f == 0) { uError() << o->name() << " is not a Folder"; return; } QString submodelFile = f->folderFile(); if (submodelFile.isEmpty()) { insert(mt_Externalize_Folder); } else { insert(mt_Internalize_Folder); } } diff --git a/umbrello/uml.cpp b/umbrello/uml.cpp index 7a90471ee..91221f9b4 100644 --- a/umbrello/uml.cpp +++ b/umbrello/uml.cpp @@ -1,3465 +1,3478 @@ /*************************************************************************** * 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 "uml.h" // app includes #include "birdview.h" #include "umlappprivate.h" #include "umldoc.h" #include "umllistview.h" #include "umlviewlist.h" #include "worktoolbar.h" #include "umlviewimageexporter.h" #include "umlviewimageexporterall.h" #include "docwindow.h" #include "optionstate.h" #include "cmdlineexportallviewsevent.h" #include "cmds.h" #include "umbrellosettings.h" #include "statusbartoolbutton.h" #include "findresults.h" // code generation #include "advancedcodegenerator.h" #include "codegenerationpolicy.h" #include "codegenfactory.h" #include "codegenpolicyext.h" #include "simplecodegenerator.h" // utils #include "debug_utils.h" #include "widget_utils.h" #include "icon_utils.h" // dialogs #include "classwizard.h" #include "codegenerationwizard.h" #include "codeimportingwizard.h" #include "codeviewerdialog.h" #include "diagramprintpage.h" #include "diagramselectiondialog.h" #include "settingsdialog.h" #include "finddialog.h" #include "classimport.h" #include "refactoringassistant.h" // clipboard #include "umlclipboard.h" #include "umldragdata.h" // docgenerators #include "docbookgenerator.h" #include "xhtmlgenerator.h" #include "umlscene.h" // kde includes #if QT_VERSION < 0x050000 #include #endif #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #if QT_VERSION < 0x050000 #include #endif #include #include #if QT_VERSION < 0x050000 #include #endif #include #if QT_VERSION < 0x050000 #include #endif #include #if QT_VERSION < 0x050000 #include #include #endif // qt includes #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #include #include #include #if QT_VERSION < 0x050000 #include #endif #include #include #include #include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #include #include #include /** Static pointer, holding the last created instance. */ UMLApp* UMLApp::s_instance; /** * Searches for a menu with the given name. * @todo This is an ugly _HACK_ to allow to compile umbrello. * All the menu stuff should be ported to KDE4 (using actions) * * @param name The name of the menu to search for (name, not text) */ QMenu* UMLApp::findMenu(const QString& name) { QWidget* widget = factory()->container(name, this); if (widget) { return dynamic_cast(widget); } DEBUG(DBG_SRC) << "factory()->container(" << name << ") returns NULL"; return 0; } DEBUG_REGISTER(UMLApp) /** * Constructor. Calls all init functions to create the application. */ UMLApp::UMLApp(QWidget* parent) : KXmlGuiWindow(parent), m_d(new UMLAppPrivate(this)), m_langSelect(0), m_zoomSelect(0), m_activeLanguage(Uml::ProgrammingLanguage::Reserved), m_codegen(0), m_commoncodegenpolicy(new CodeGenerationPolicy()), m_policyext(0), #if QT_VERSION >= 0x050000 m_config(KSharedConfig::openConfig()), #else m_config(KGlobal::config()), #endif m_view(0), m_doc(new UMLDoc()), m_listView(0), m_docWindow(0), m_birdView(0), m_refactoringAssist(0), m_clipTimer(0), m_copyTimer(0), m_loading(false), m_imageMimeType(QString()), m_settingsDialog(0), m_imageExporterAll(new UMLViewImageExporterAll()), m_xhtmlGenerator(0), #if QT_VERSION >= 0x050000 m_pUndoStack(new QUndoStack(this)), #else m_pUndoStack(new KUndoStack(this)), #endif m_hasBegunMacro(false), m_printSettings(0), m_printer(new QPrinter()) { s_instance = this; m_doc->init(); m_printer->setFullPage(true); layout()->setSizeConstraint(QLayout::SetNoConstraint); readOptionState(); initActions(); // call this here because the statusBar is shown/hidden by setupGUI() initStatusBar(); // use the absolute path to your umbrelloui.rc file for testing purpose in setupGUI(); StandardWindowOptions opt = Default; opt &= ~Save; QString xmlFile = QLatin1String(UMBRELLOUI_RC); QFileInfo fi(xmlFile); setupGUI(opt, fi.exists() ? xmlFile : QString()); initView(); initClip(); readOptions(); //get a reference to the Code->Active Language and to the Diagram->Zoom menu m_langSelect = findMenu(QLatin1String("active_lang_menu")); //in case langSelect hasn't been initialized we create the Popup menu. //it will be hidden, but at least we wont crash if someone takes the entry away from the ui.rc file if (m_langSelect == 0) { m_langSelect = new QMenu(QLatin1String("active_lang_menu"), this); } m_zoomSelect = findMenu(QLatin1String("zoom_menu")); //in case zoomSelect hasn't been initialized we create the Popup menu. //it will be hidden, but at least we wont crash if some one takes the entry away from the ui.rc file if (m_zoomSelect == 0) { m_zoomSelect = new QMenu(QLatin1String("zoom_menu"), this); } //connect zoomSelect menu connect(m_zoomSelect, SIGNAL(aboutToShow()), this, SLOT(setupZoomMenu())); connect(m_zoomSelect, SIGNAL(triggered(QAction*)), this, SLOT(slotSetZoom(QAction*))); setAutoSaveSettings(); m_toolsbar->setToolButtonStyle(Qt::ToolButtonIconOnly); // too many items for text, really we want a toolbox widget } /** * Standard deconstructor. */ UMLApp::~UMLApp() { disconnect(m_pZoomInPB, SIGNAL(clicked()), this, SLOT(slotZoomIn())); disconnect(m_pZoomSlider, SIGNAL(valueChanged(int)), this, SLOT(slotZoomSliderMoved(int))); #if QT_VERSION >= 0x050000 disconnect(m_tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(slotCloseDiagram(int))); disconnect(m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(slotTabChanged(int))); disconnect(m_tabWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotDiagramPopupMenu(QPoint))); #else disconnect(m_tabWidget, SIGNAL(closeRequest(QWidget*)), this, SLOT(slotCloseDiagram(QWidget*))); disconnect(m_tabWidget, SIGNAL(currentChanged(QWidget*)), this, SLOT(slotTabChanged(QWidget*))); disconnect(m_tabWidget, SIGNAL(contextMenu(QWidget*,QPoint)), m_doc, SLOT(slotDiagramPopupMenu(QWidget*,QPoint))); #endif delete m_birdView; delete m_clipTimer; delete m_copyTimer; delete m_commoncodegenpolicy; delete m_imageExporterAll; delete m_printer; delete m_policyext; delete m_pUndoStack; m_pUndoStack = 0; delete m_refactoringAssist; delete m_xhtmlGenerator; delete m_listView; delete m_doc; delete m_d; } /** * Get the last created instance of this class. */ UMLApp* UMLApp::app() { return s_instance; } /** * Helper method to setup the programming language action. */ void UMLApp::setProgLangAction(Uml::ProgrammingLanguage::Enum pl, const char* name, const char* action) { m_langAct[pl] = actionCollection()->addAction(QString::fromLatin1(action)); m_langAct[pl]->setText(QString::fromLatin1(name)); m_langAct[pl]->setCheckable(true); } /** * Initializes the KActions and the status bar of the application * and calls setupGUI(). * Note: Check also the file umbrelloui.rc and add actions there too. */ void UMLApp::initActions() { QAction* fileNew = KStandardAction::openNew(this, SLOT(slotFileNew()), actionCollection()); QAction* fileOpen = KStandardAction::open(this, SLOT(slotFileOpen()), actionCollection()); #if QT_VERSION >= 0x050000 fileOpenRecent = KStandardAction::openRecent(this, SLOT(slotFileOpenRecent(QUrl)), actionCollection()); #else fileOpenRecent = KStandardAction::openRecent(this, SLOT(slotFileOpenRecent(KUrl)), actionCollection()); #endif QAction* fileSave = KStandardAction::save(this, SLOT(slotFileSave()), actionCollection()); QAction* fileSaveAs = KStandardAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection()); QAction* fileClose = KStandardAction::close(this, SLOT(slotFileClose()), actionCollection()); filePrint = KStandardAction::print(this, SLOT(slotFilePrint()), actionCollection()); KStandardAction::find(this, SLOT(slotFind()), actionCollection()); KStandardAction::findNext(this, SLOT(slotFindNext()), actionCollection()); KStandardAction::findPrev(this, SLOT(slotFindPrevious()), actionCollection()); printPreview = KStandardAction::printPreview(this, SLOT(slotPrintPreview()), actionCollection()); #if QT_VERSION >= 0x040600 filePrint->setPriority(QAction::LowPriority); // icon only printPreview->setPriority(QAction::LowPriority); // icon only #endif QAction* fileQuit = KStandardAction::quit(this, SLOT(slotFileQuit()), actionCollection()); editUndo = m_pUndoStack->createUndoAction(actionCollection()); editRedo = m_pUndoStack->createRedoAction(actionCollection()); #if QT_VERSION >= 0x040600 editUndo->setPriority(QAction::LowPriority); // icon only editRedo->setPriority(QAction::LowPriority); // icon only #endif disconnect(m_pUndoStack, SIGNAL(undoTextChanged(QString)), editUndo, 0); disconnect(m_pUndoStack, SIGNAL(redoTextChanged(QString)), editRedo, 0); editCut = KStandardAction::cut(this, SLOT(slotEditCut()), actionCollection()); editCopy = KStandardAction::copy(this, SLOT(slotEditCopy()), actionCollection()); editPaste = KStandardAction::paste(this, SLOT(slotEditPaste()), actionCollection()); createStandardStatusBarAction(); setStandardToolBarMenuEnabled(true); /* QAction* selectAll = */ KStandardAction::selectAll(this, SLOT(slotSelectAll()), actionCollection()); QAction* fileExportDocbook = actionCollection()->addAction(QLatin1String("file_export_docbook")); fileExportDocbook->setText(i18n("&Export model to DocBook")); connect(fileExportDocbook, SIGNAL(triggered(bool)), this, SLOT(slotFileExportDocbook())); QAction* fileExportXhtml = actionCollection()->addAction(QLatin1String("file_export_xhtml")); fileExportXhtml->setText(i18n("&Export model to XHTML")); connect(fileExportXhtml, SIGNAL(triggered(bool)), this, SLOT(slotFileExportXhtml())); QAction* classWizard = actionCollection()->addAction(QLatin1String("class_wizard")); classWizard->setText(i18n("&New Class Wizard...")); connect(classWizard, SIGNAL(triggered(bool)), this, SLOT(slotClassWizard())); QAction* addDefDatatypes = actionCollection()->addAction(QLatin1String("create_default_datatypes")); addDefDatatypes->setText(i18n("&Add Default Datatypes for Active Language")); connect(addDefDatatypes, SIGNAL(triggered(bool)), this, SLOT(slotAddDefaultDatatypes())); QAction* preferences = KStandardAction::preferences(this, SLOT(slotPrefs()), actionCollection()); QAction* impWizard = actionCollection()->addAction(QLatin1String("importing_wizard")); impWizard->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Import_Files)); impWizard->setText(i18n("Code &Importing Wizard...")); connect(impWizard, SIGNAL(triggered(bool)), this, SLOT(slotImportingWizard())); QAction* importProject = actionCollection()->addAction(QLatin1String("import_project")); importProject->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Import_Project)); importProject->setText(i18n("Import from Directory...")); connect(importProject, SIGNAL(triggered(bool)), this, SLOT(slotImportProject())); QAction* genWizard = actionCollection()->addAction(QLatin1String("generation_wizard")); genWizard->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Export_Files)); genWizard->setText(i18n("&Code Generation Wizard...")); connect(genWizard, SIGNAL(triggered(bool)), this, SLOT(slotExecGenerationWizard())); QAction* genAll = actionCollection()->addAction(QLatin1String("generate_all")); genAll->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Export_Files)); genAll->setText(i18n("&Generate All Code")); connect(genAll, SIGNAL(triggered(bool)), this, SLOT(slotGenerateAllCode())); setProgLangAction(Uml::ProgrammingLanguage::ActionScript, "ActionScript", "setLang_actionscript"); setProgLangAction(Uml::ProgrammingLanguage::Ada, "Ada", "setLang_ada"); setProgLangAction(Uml::ProgrammingLanguage::Cpp, "C++", "setLang_cpp"); setProgLangAction(Uml::ProgrammingLanguage::CSharp, "C#", "setLang_csharp"); setProgLangAction(Uml::ProgrammingLanguage::D, "D", "setLang_d"); setProgLangAction(Uml::ProgrammingLanguage::IDL, "IDL", "setLang_idl"); setProgLangAction(Uml::ProgrammingLanguage::Java, "Java", "setLang_java"); setProgLangAction(Uml::ProgrammingLanguage::JavaScript, "JavaScript", "setLang_javascript"); setProgLangAction(Uml::ProgrammingLanguage::MySQL, "MySQL (SQL)", "setLang_mysql"); setProgLangAction(Uml::ProgrammingLanguage::Pascal, "Pascal", "setLang_pascal"); setProgLangAction(Uml::ProgrammingLanguage::Perl, "Perl", "setLang_perl"); setProgLangAction(Uml::ProgrammingLanguage::PHP, "PHP", "setLang_php"); setProgLangAction(Uml::ProgrammingLanguage::PHP5, "PHP5", "setLang_php5"); setProgLangAction(Uml::ProgrammingLanguage::PostgreSQL, "PostgreSQL(SQL)", "setLang_postgresql"); setProgLangAction(Uml::ProgrammingLanguage::Python, "Python", "setLang_python"); setProgLangAction(Uml::ProgrammingLanguage::Ruby, "Ruby", "setLang_ruby"); setProgLangAction(Uml::ProgrammingLanguage::SQL, "SQL", "setLang_sql"); setProgLangAction(Uml::ProgrammingLanguage::Tcl, "Tcl", "setLang_tcl"); setProgLangAction(Uml::ProgrammingLanguage::Vala, "Vala", "setLang_vala"); setProgLangAction(Uml::ProgrammingLanguage::XMLSchema, "XMLSchema", "setLang_xmlschema"); connect(m_langAct[Uml::ProgrammingLanguage::ActionScript], SIGNAL(triggered()), this, SLOT(setLang_actionscript())); connect(m_langAct[Uml::ProgrammingLanguage::Ada], SIGNAL(triggered()), this, SLOT(setLang_ada())); connect(m_langAct[Uml::ProgrammingLanguage::Cpp], SIGNAL(triggered()), this, SLOT(setLang_cpp())); connect(m_langAct[Uml::ProgrammingLanguage::CSharp], SIGNAL(triggered()), this, SLOT(setLang_csharp())); connect(m_langAct[Uml::ProgrammingLanguage::D], SIGNAL(triggered()), this, SLOT(setLang_d())); connect(m_langAct[Uml::ProgrammingLanguage::IDL], SIGNAL(triggered()), this, SLOT(setLang_idl())); connect(m_langAct[Uml::ProgrammingLanguage::Java], SIGNAL(triggered()), this, SLOT(setLang_java())); connect(m_langAct[Uml::ProgrammingLanguage::JavaScript], SIGNAL(triggered()), this, SLOT(setLang_javascript())); connect(m_langAct[Uml::ProgrammingLanguage::MySQL], SIGNAL(triggered()), this, SLOT(setLang_mysql())); connect(m_langAct[Uml::ProgrammingLanguage::Pascal], SIGNAL(triggered()), this, SLOT(setLang_pascal())); connect(m_langAct[Uml::ProgrammingLanguage::Perl], SIGNAL(triggered()), this, SLOT(setLang_perl())); connect(m_langAct[Uml::ProgrammingLanguage::PHP], SIGNAL(triggered()), this, SLOT(setLang_php())); connect(m_langAct[Uml::ProgrammingLanguage::PHP5], SIGNAL(triggered()), this, SLOT(setLang_php5())); connect(m_langAct[Uml::ProgrammingLanguage::PostgreSQL], SIGNAL(triggered()), this, SLOT(setLang_postgresql())); connect(m_langAct[Uml::ProgrammingLanguage::Python], SIGNAL(triggered()), this, SLOT(setLang_python())); connect(m_langAct[Uml::ProgrammingLanguage::Ruby], SIGNAL(triggered()), this, SLOT(setLang_ruby())); connect(m_langAct[Uml::ProgrammingLanguage::SQL], SIGNAL(triggered()), this, SLOT(setLang_sql())); connect(m_langAct[Uml::ProgrammingLanguage::Tcl], SIGNAL(triggered()), this, SLOT(setLang_tcl())); connect(m_langAct[Uml::ProgrammingLanguage::Vala], SIGNAL(triggered()), this, SLOT(setLang_vala())); connect(m_langAct[Uml::ProgrammingLanguage::XMLSchema], SIGNAL(triggered()), this, SLOT(setLang_xmlschema())); fileNew->setToolTip(i18n("Creates a new document")); fileOpen->setToolTip(i18n("Opens an existing document")); fileOpenRecent->setToolTip(i18n("Opens a recently used file")); fileSave->setToolTip(i18n("Saves the document")); fileSaveAs->setToolTip(i18n("Saves the document as...")); fileClose->setToolTip(i18n("Closes the document")); filePrint->setToolTip(i18n("Prints out the document")); printPreview->setToolTip(i18n("Print Preview of the document")); fileQuit->setToolTip(i18n("Quits the application")); fileExportDocbook->setToolTip(i18n("Exports the model to the docbook format")); fileExportXhtml->setToolTip(i18n("Exports the model to the XHTML format")); editCut->setToolTip(i18n("Cuts the selected section and puts it to the clipboard")); editCopy->setToolTip(i18n("Copies the selected section to the clipboard")); editPaste->setToolTip(i18n("Pastes the contents of the clipboard")); preferences->setToolTip(i18n("Set the default program preferences")); deleteSelectedWidget = actionCollection()->addAction(QLatin1String("delete_selected")); deleteSelectedWidget->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Delete)); deleteSelectedWidget->setText(i18nc("delete selected widget", "Delete &Selected")); deleteSelectedWidget->setShortcut(QKeySequence(Qt::Key_Delete)); connect(deleteSelectedWidget, SIGNAL(triggered(bool)), this, SLOT(slotDeleteSelected())); // The different views newDiagram = actionCollection()->add(QLatin1String("new_view")); newDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_New)); newDiagram->setText(QLatin1String("new_view")); QAction* classDiagram = actionCollection()->addAction(QLatin1String("new_class_diagram")); classDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Class)); classDiagram->setText(i18n("&Class Diagram...")); connect(classDiagram, SIGNAL(triggered(bool)), this, SLOT(slotClassDiagram())); newDiagram->addAction(classDiagram); #ifdef ENABLE_OBJECT_DIAGRAM QAction* objectDiagram = actionCollection()->addAction(QLatin1String("new_object_diagram")); objectDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Object)); objectDiagram->setText(i18n("&Object Diagram...")); connect(objectDiagram, SIGNAL(triggered()), this, SLOT(slotObjectDiagram())); newDiagram->addAction(objectDiagram); #endif QAction* sequenceDiagram= actionCollection()->addAction(QLatin1String("new_sequence_diagram")); sequenceDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Sequence)); sequenceDiagram->setText(i18n("&Sequence Diagram...")); connect(sequenceDiagram, SIGNAL(triggered(bool)), this, SLOT(slotSequenceDiagram())); newDiagram->addAction(sequenceDiagram); QAction* collaborationDiagram = actionCollection()->addAction(QLatin1String("new_collaboration_diagram")); collaborationDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Collaboration)); collaborationDiagram->setText(i18n("C&ommunication Diagram...")); connect(collaborationDiagram, SIGNAL(triggered(bool)), this, SLOT(slotCollaborationDiagram())); newDiagram->addAction(collaborationDiagram); QAction* useCaseDiagram = actionCollection()->addAction(QLatin1String("new_use_case_diagram")); useCaseDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Usecase)); useCaseDiagram->setText(i18n("&Use Case Diagram...")); connect(useCaseDiagram, SIGNAL(triggered(bool)), this, SLOT(slotUseCaseDiagram())); newDiagram->addAction(useCaseDiagram); QAction* stateDiagram = actionCollection()->addAction(QLatin1String("new_state_diagram")); stateDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_State)); stateDiagram->setText(i18n("S&tate Diagram...")); connect(stateDiagram, SIGNAL(triggered(bool)), this, SLOT(slotStateDiagram())); newDiagram->addAction(stateDiagram); QAction* activityDiagram = actionCollection()->addAction(QLatin1String("new_activity_diagram")); activityDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Activity)); activityDiagram->setText(i18n("&Activity Diagram...")); connect(activityDiagram, SIGNAL(triggered(bool)), this, SLOT(slotActivityDiagram())); newDiagram->addAction(activityDiagram); QAction* componentDiagram = actionCollection()->addAction(QLatin1String("new_component_diagram")); componentDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Component)); componentDiagram->setText(i18n("Co&mponent Diagram...")); connect(componentDiagram, SIGNAL(triggered(bool)), this, SLOT(slotComponentDiagram())); newDiagram->addAction(componentDiagram); QAction* deploymentDiagram = actionCollection()->addAction(QLatin1String("new_deployment_diagram")); deploymentDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_Deployment)); deploymentDiagram->setText(i18n("&Deployment Diagram...")); connect(deploymentDiagram, SIGNAL(triggered(bool)), this, SLOT(slotDeploymentDiagram())); newDiagram->addAction(deploymentDiagram); QAction* entityRelationshipDiagram = actionCollection()->addAction(QLatin1String("new_entityrelationship_diagram")); entityRelationshipDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Diagram_EntityRelationship)); entityRelationshipDiagram->setText(i18n("&Entity Relationship Diagram...")); connect(entityRelationshipDiagram, SIGNAL(triggered(bool)), this, SLOT(slotEntityRelationshipDiagram())); newDiagram->addAction(entityRelationshipDiagram); viewShowTree = actionCollection()->add(QLatin1String("view_show_tree")); viewShowTree->setText(i18n("&Tree View")); connect(viewShowTree, SIGNAL(triggered(bool)), this, SLOT(slotShowTreeView(bool))); viewShowDebug = actionCollection()->add(QLatin1String("view_show_debug")); viewShowDebug->setText(i18n("&Debugging")); connect(viewShowDebug, SIGNAL(triggered(bool)), this, SLOT(slotShowDebugView(bool))); viewShowDoc = actionCollection()->add(QLatin1String("view_show_doc")); viewShowDoc->setText(i18n("&Documentation")); connect(viewShowDoc, SIGNAL(triggered(bool)), this, SLOT(slotShowDocumentationView(bool))); viewShowLog = actionCollection()->add(QLatin1String("view_show_log")); viewShowLog->setText(i18n("&Logging")); connect(viewShowLog, SIGNAL(triggered(bool)), this, SLOT(slotShowLogView(bool))); viewShowCmdHistory = actionCollection()->add(QLatin1String("view_show_undo")); viewShowCmdHistory->setText(i18n("&Command history")); connect(viewShowCmdHistory, SIGNAL(triggered(bool)), this, SLOT(slotShowCmdHistoryView(bool))); viewShowBirdView = actionCollection()->add(QLatin1String("view_show_bird")); viewShowBirdView->setText(i18n("&Bird's eye view")); connect(viewShowBirdView, SIGNAL(triggered(bool)), this, SLOT(slotShowBirdView(bool))); viewClearDiagram = actionCollection()->addAction(QLatin1String("view_clear_diagram")); viewClearDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Clear)); viewClearDiagram->setText(i18n("&Clear Diagram")); connect(viewClearDiagram, SIGNAL(triggered(bool)), this, SLOT(slotCurrentViewClearDiagram())); viewSnapToGrid = actionCollection()->add(QLatin1String("view_snap_to_grid")); viewSnapToGrid->setText(i18n("&Snap to Grid")); connect(viewSnapToGrid, SIGNAL(triggered(bool)), this, SLOT(slotCurrentViewToggleSnapToGrid())); viewShowGrid = actionCollection()->add(QLatin1String("view_show_grid")); viewShowGrid->setText(i18n("S&how Grid")); connect(viewShowGrid, SIGNAL(triggered(bool)), this, SLOT(slotCurrentViewToggleShowGrid())); deleteDiagram = actionCollection()->addAction(QLatin1String("view_delete")); deleteDiagram->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Delete)); deleteDiagram->setText(i18n("&Delete Diagram")); connect(deleteDiagram, SIGNAL(triggered(bool)), this, SLOT(slotDeleteDiagram())); viewExportImage = actionCollection()->addAction(QLatin1String("view_export_image")); viewExportImage->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Export_Picture)); viewExportImage->setText(i18n("&Export as Picture...")); connect(viewExportImage, SIGNAL(triggered(bool)), this, SLOT(slotCurrentViewExportImage())); QAction* viewExportImageAll = actionCollection()->addAction(QLatin1String("view_export_images")); viewExportImageAll->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Export_Picture)); viewExportImageAll->setText(i18n("Export &Diagrams as Pictures...")); connect(viewExportImageAll, SIGNAL(triggered(bool)), this, SLOT(slotViewsExportImages())); viewProperties = actionCollection()->addAction(QLatin1String("view_properties")); viewProperties->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Properties)); viewProperties->setText(i18n("&Properties")); connect(viewProperties, SIGNAL(triggered(bool)), this, SLOT(slotCurrentProperties())); viewSnapToGrid->setChecked(false); viewShowGrid->setChecked(false); viewClearDiagram->setEnabled(false); viewSnapToGrid->setEnabled(false); viewShowGrid->setEnabled(false); deleteDiagram->setEnabled(false); viewExportImage->setEnabled(false); viewProperties->setEnabled(false); zoom100Action = actionCollection()->addAction(QLatin1String("zoom100")); zoom100Action->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Zoom_100)); zoom100Action->setText(i18n("Z&oom to 100%")); connect(zoom100Action, SIGNAL(triggered(bool)), this, SLOT(slotZoom100())); QAction* alignRight = actionCollection()->addAction(QLatin1String("align_right")); alignRight->setText(i18n("Align Right")); alignRight->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_Right)); connect(alignRight, SIGNAL(triggered(bool)), this, SLOT(slotAlignRight())); QAction* alignLeft = actionCollection()->addAction(QLatin1String("align_left")); alignLeft->setText(i18n("Align Left")); alignLeft->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_Left)); connect(alignLeft, SIGNAL(triggered(bool)), this, SLOT(slotAlignLeft())); QAction* alignTop = actionCollection()->addAction(QLatin1String("align_top")); alignTop->setText(i18n("Align Top")); alignTop->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_Top)); connect(alignTop, SIGNAL(triggered(bool)), this, SLOT(slotAlignTop())); QAction* alignBottom = actionCollection()->addAction(QLatin1String("align_bottom")); alignBottom->setText(i18n("Align Bottom")); alignBottom->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_Bottom)); connect(alignBottom, SIGNAL(triggered(bool)), this, SLOT(slotAlignBottom())); QAction* alignVerticalMiddle = actionCollection()->addAction(QLatin1String("align_vertical_middle")); alignVerticalMiddle->setText(i18n("Align Vertical Middle")); alignVerticalMiddle->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_VerticalMiddle)); connect(alignVerticalMiddle, SIGNAL(triggered(bool)), this, SLOT(slotAlignVerticalMiddle())); QAction* alignHorizontalMiddle = actionCollection()->addAction(QLatin1String("align_horizontal_middle")); alignHorizontalMiddle->setText(i18n("Align Horizontal Middle")); alignHorizontalMiddle->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_HorizontalMiddle)); connect(alignHorizontalMiddle, SIGNAL(triggered(bool)), this, SLOT(slotAlignHorizontalMiddle())); QAction* alignVerticalDistribute = actionCollection()->addAction(QLatin1String("align_vertical_distribute")); alignVerticalDistribute->setText(i18n("Align Vertical Distribute")); alignVerticalDistribute->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_VerticalDistribute)); connect(alignVerticalDistribute, SIGNAL(triggered(bool)), this, SLOT(slotAlignVerticalDistribute())); QAction* alignHorizontalDistribute = actionCollection()->addAction(QLatin1String("align_horizontal_distribute")); alignHorizontalDistribute->setText(i18n("Align Horizontal Distribute")); alignHorizontalDistribute->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Align_HorizontalDistribute)); connect(alignHorizontalDistribute, SIGNAL(triggered(bool)), this, SLOT(slotAlignHorizontalDistribute())); QString moveTabLeftString = i18n("&Move Tab Left"); QString moveTabRightString = i18n("&Move Tab Right"); #if QT_VERSION >= 0x050000 QAction* moveTabLeft = actionCollection()->addAction(QLatin1String("move_tab_left")); #else KAction* moveTabLeft = actionCollection()->addAction(QLatin1String("move_tab_left")); #endif moveTabLeft->setIcon(Icon_Utils::SmallIcon(QApplication::layoutDirection() ? Icon_Utils::it_Go_Next : Icon_Utils::it_Go_Previous)); moveTabLeft->setText(QApplication::layoutDirection() ? moveTabRightString : moveTabLeftString); moveTabLeft->setShortcut(QApplication::layoutDirection() ? QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_Right) : QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_Left)); connect(moveTabLeft, SIGNAL(triggered(bool)), this, SLOT(slotMoveTabLeft())); #if QT_VERSION >= 0x050000 QAction* moveTabRight = actionCollection()->addAction(QLatin1String("move_tab_right")); #else KAction* moveTabRight = actionCollection()->addAction(QLatin1String("move_tab_right")); #endif moveTabRight->setIcon(Icon_Utils::SmallIcon(QApplication::layoutDirection() ? Icon_Utils::it_Go_Previous : Icon_Utils::it_Go_Next)); moveTabRight->setText(QApplication::layoutDirection() ? moveTabLeftString : moveTabRightString); moveTabRight->setShortcut(QApplication::layoutDirection() ? QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_Left) : QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_Right)); connect(moveTabRight, SIGNAL(triggered(bool)), this, SLOT(slotMoveTabRight())); QString selectTabLeftString = i18n("Select Diagram on Left"); QString selectTabRightString = i18n("Select Diagram on Right"); #if QT_VERSION >= 0x050000 QAction* changeTabLeft = actionCollection()->addAction(QLatin1String("previous_tab")); #else KAction* changeTabLeft = actionCollection()->addAction(QLatin1String("previous_tab")); #endif changeTabLeft->setText(QApplication::layoutDirection() ? selectTabRightString : selectTabLeftString); changeTabLeft->setShortcut(QApplication::layoutDirection() ? QKeySequence(Qt::SHIFT+Qt::Key_Right) : QKeySequence(Qt::SHIFT+Qt::Key_Left)); connect(changeTabLeft, SIGNAL(triggered(bool)), this, SLOT(slotChangeTabLeft())); #if QT_VERSION >= 0x050000 QAction* changeTabRight = actionCollection()->addAction(QLatin1String("next_tab")); #else KAction* changeTabRight = actionCollection()->addAction(QLatin1String("next_tab")); #endif changeTabRight->setText(QApplication::layoutDirection() ? selectTabLeftString : selectTabRightString); changeTabRight->setShortcut(QApplication::layoutDirection() ? QKeySequence(Qt::SHIFT+Qt::Key_Left) : QKeySequence(Qt::SHIFT+Qt::Key_Right)); connect(changeTabRight, SIGNAL(triggered(bool)), this, SLOT(slotChangeTabRight())); // @todo Check if this should be ported // QMenu* menu = findMenu(QLatin1String("settings")); // menu->insertItem(i18n("&Windows"), dockHideShowMenu(), -1, 0); // disable actions at startup fileSave->setEnabled(true); fileSaveAs->setEnabled(true); enablePrint(false); editCut->setEnabled(false); editCopy->setEnabled(false); editPaste->setEnabled(false); editUndo->setEnabled(false); editRedo->setEnabled(false); } /** * Connected to by the zoomAction, a value of between 300 * and 2200 is scaled to zoom to between 9% and 525%. * The min and max values of the slider are hard coded in the statusbar slider. */ void UMLApp::slotZoomSliderMoved(int value) { setZoom(value); } /** * Set zoom to fit the view. */ void UMLApp::slotZoomFit() { QRectF items = currentView()->umlScene()->itemsBoundingRect(); if (items.isNull()) { setZoom(100); return; } currentView()->umlScene()->setSceneRect(items); // TODO: QGraphicsView seems not to be informed about the scene rect update currentView()->setSceneRect(items); int scaleW = ceil(100.0 * currentView()->viewport()->width() / currentView()->umlScene()->width()); int scaleH = ceil(100.0 * currentView()->viewport()->height() / currentView()->umlScene()->height()); int scale = 100; if (scaleW < scaleH) { scale = scaleW; } else { scale = scaleH; } if (scale < 0) scale = 100; else if (scale > 500) scale = 500; else scale -= 2; setZoom(scale); } /** * Set zoom to 100%. */ void UMLApp::slotZoom100() { setZoom(100); } /** * Decrease the zoom factor of the current diagram. */ void UMLApp::slotZoomOut() { setZoom(currentView()->zoom()-5); } /** * Increase the zoom factor of the current diagram. */ void UMLApp::slotZoomIn() { setZoom(currentView()->zoom()+5); } /** * Set the zoom factor of the current diagram. * * @param zoom Zoom factor in percentage. * @param withView also setup the currently displayed diagram */ void UMLApp::setZoom(int zoom, bool withView) { if (withView) currentView()->setZoom(zoom); bool oldState = m_pZoomSlider->blockSignals(true); m_pZoomSlider->setValue(zoom); m_pZoomSlider->blockSignals(oldState); m_zoomValueLbl->setText(QString::number(zoom) + QLatin1Char('%')); } /** * Set the zoom factor of the current diagram. * * @param action Action which is called. */ void UMLApp::slotSetZoom(QAction* action) { QVariant var = action->data(); if (var.canConvert()) { setZoom(var.toInt()); } } /** * Helper method to create the zoom actions. */ QAction* UMLApp::createZoomAction(int zoom, int currentZoom) { //IMPORTANT: The zoom value is added to the action. QAction* action = new QAction(this); action->setCheckable(true); action->setText(i18nc("%1 percent value from 20 to 500", " &%1%", zoom)); action->setData(zoom); if (zoom == currentZoom) { action->setChecked(true); } return action; } /** * Prepares the zoom menu for display. */ void UMLApp::setupZoomMenu() { m_zoomSelect->clear(); int currentZoom = currentView()->zoom(); m_zoomSelect->addAction(createZoomAction(33, currentZoom)); m_zoomSelect->addAction(createZoomAction(50, currentZoom)); m_zoomSelect->addAction(createZoomAction(75, currentZoom)); m_zoomSelect->addAction(createZoomAction(100, currentZoom)); m_zoomSelect->addAction(createZoomAction(150, currentZoom)); m_zoomSelect->addAction(createZoomAction(200, currentZoom)); m_zoomSelect->addAction(createZoomAction(300, currentZoom)); // if currentZoom is not a "standard zoom" (because of zoom in / zoom out step // we add it for information switch (currentZoom) { case 33: case 50: case 75: case 100: case 150: case 200: case 300: break; default: m_zoomSelect->addSeparator(); m_zoomSelect->addAction(createZoomAction(currentZoom, currentZoom)); } } /** * Sets up the statusbar for the main window by * initialzing a statuslabel. */ void UMLApp::initStatusBar() { connect(m_doc, SIGNAL(sigWriteToStatusBar(QString)), this, SLOT(slotStatusMsg(QString))); m_statusBarMessage = new QLabel(i18nc("init status bar", "Ready")); statusBar()->addWidget(m_statusBarMessage); QWidget* defaultZoomWdg = new QWidget(this); QHBoxLayout* zoomLayout = new QHBoxLayout(defaultZoomWdg); zoomLayout->setContentsMargins(0, 0, 0, 0); zoomLayout->setSpacing(0); zoomLayout->addItem(new QSpacerItem(0, 20, QSizePolicy::Expanding, QSizePolicy::Minimum)); m_zoomValueLbl = new QLabel(i18n("100%")); m_zoomValueLbl->setContentsMargins(10, 0, 10, 0); zoomLayout->addWidget(m_zoomValueLbl); m_pZoomFitSBTB = new StatusBarToolButton(this); m_pZoomFitSBTB->setText(i18n("Fit")); m_pZoomFitSBTB->setGroupPosition(StatusBarToolButton::GroupLeft); zoomLayout->addWidget(m_pZoomFitSBTB); m_pZoomFitSBTB->setContentsMargins(0, 0, 0, 0); //m_pZoomFitSBTB->setDisabled(true); connect(m_pZoomFitSBTB, SIGNAL(clicked()), this, SLOT(slotZoomFit())); m_pZoomFullSBTB = new StatusBarToolButton(this); m_pZoomFullSBTB->setText(i18n("100%")); m_pZoomFullSBTB->setGroupPosition(StatusBarToolButton::GroupRight); m_pZoomFullSBTB->setContentsMargins(0, 0, 0, 0); zoomLayout->addWidget(m_pZoomFullSBTB); connect(m_pZoomFullSBTB, SIGNAL(clicked()), this, SLOT(slotZoom100())); statusBar()->addPermanentWidget(defaultZoomWdg); m_pZoomOutPB = new QPushButton(this); #if QT_VERSION >= 0x050000 m_pZoomOutPB->setIcon(QIcon(QLatin1String("zoom-out"))); #else m_pZoomOutPB->setIcon(KIcon(QLatin1String("zoom-out"))); #endif m_pZoomOutPB->setFlat(true); m_pZoomOutPB->setMaximumSize(30, 30); statusBar()->addPermanentWidget(m_pZoomOutPB); connect(m_pZoomOutPB, SIGNAL(clicked()), this, SLOT(slotZoomOut())); m_pZoomSlider = new QSlider(Qt::Horizontal, this); m_pZoomSlider->setMaximumSize(100, 50); m_pZoomSlider->setMinimum (20); m_pZoomSlider->setMaximum (480); //m_pZoomSlider->setPageStep (1000); m_pZoomSlider->setValue (100); m_pZoomSlider->setContentsMargins(0, 0, 0, 0); connect(m_pZoomSlider, SIGNAL(valueChanged(int)), this, SLOT(slotZoomSliderMoved(int))); statusBar()->addPermanentWidget(m_pZoomSlider); m_pZoomInPB = new QPushButton(this); #if QT_VERSION >= 0x050000 m_pZoomInPB->setIcon(QIcon(QLatin1String("zoom-in"))); #else m_pZoomInPB->setIcon(KIcon(QLatin1String("zoom-in"))); #endif m_pZoomInPB->setFlat(true); m_pZoomInPB->setMaximumSize(30, 30); statusBar()->addPermanentWidget(m_pZoomInPB); connect(m_pZoomInPB, SIGNAL(clicked()), this, SLOT(slotZoomIn())); } /** * Creates the centerwidget of the KMainWindow instance and * sets it as the view. */ void UMLApp::initView() { setCaption(m_doc->url().fileName(), false); m_view = 0; m_toolsbar = new WorkToolBar(this); m_toolsbar->setWindowTitle(i18n("Diagram Toolbar")); addToolBar(Qt::TopToolBarArea, m_toolsbar); // m_mainDock = new QDockWidget(this); // addDockWidget (Qt::RightDockWidgetArea, m_mainDock); m_newSessionButton = 0; m_diagramMenu = 0; // Prepare Stacked Diagram Representation m_viewStack = new QStackedWidget(this); // Prepare Tabbed Diagram Representation #if QT_VERSION >= 0x050000 m_tabWidget = new QTabWidget(this); m_tabWidget->setMovable(true); connect(m_tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(slotCloseDiagram(int))); connect(m_tabWidget, SIGNAL(currentChanged(int)), SLOT(slotTabChanged(int))); connect(m_tabWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotDiagramPopupMenu(QPoint))); #else m_tabWidget = new KTabWidget(this); m_tabWidget->setAutomaticResizeTabs(true); connect(m_tabWidget, SIGNAL(closeRequest(QWidget*)), SLOT(slotCloseDiagram(QWidget*))); connect(m_tabWidget, SIGNAL(currentChanged(QWidget*)), SLOT(slotTabChanged(QWidget*))); connect(m_tabWidget, SIGNAL(contextMenu(QWidget*,QPoint)), m_doc, SLOT(slotDiagramPopupMenu(QWidget*,QPoint))); #endif m_tabWidget->setTabsClosable(true); m_newSessionButton = new QToolButton(m_tabWidget); m_newSessionButton->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Tab_New)); m_newSessionButton->adjustSize(); m_newSessionButton->setAutoRaise(true); m_newSessionButton->setPopupMode(QToolButton::InstantPopup); m_newSessionButton->setMenu(newDiagram->menu()); m_tabWidget->setCornerWidget(m_newSessionButton, Qt::TopLeftCorner); m_newSessionButton->installEventFilter(this); m_layout = new QVBoxLayout; m_layout->setMargin(0); if (Settings::optionState().generalState.tabdiagrams) { // Tabbed Diagram Representation m_layout->addWidget(m_tabWidget); m_viewStack->hide(); } else { // Stacked Diagram Representation m_layout->addWidget(m_viewStack); m_tabWidget->hide(); } QWidget *widget = new QWidget; widget->setLayout(m_layout); setCentralWidget(widget); // create the tree viewer m_listDock = new QDockWidget(i18n("&Tree View"), this); m_listDock->setObjectName(QLatin1String("TreeViewDock")); addDockWidget(Qt::LeftDockWidgetArea, m_listDock); m_listView = new UMLListView(m_listDock); //m_listView->setSorting(-1); m_listView->setDocument(m_doc); m_listView->init(); m_listDock->setWidget(m_listView); connect(m_listDock, SIGNAL(visibilityChanged(bool)), viewShowTree, SLOT(setChecked(bool))); // create the documentation viewer m_documentationDock = new QDockWidget(i18n("Doc&umentation"), this); m_documentationDock->setObjectName(QLatin1String("DocumentationDock")); addDockWidget(Qt::LeftDockWidgetArea, m_documentationDock); m_docWindow = new DocWindow(m_doc, m_documentationDock); m_docWindow->setObjectName(QLatin1String("DOCWINDOW")); m_documentationDock->setWidget(m_docWindow); connect(m_documentationDock, SIGNAL(visibilityChanged(bool)), viewShowDoc, SLOT(setChecked(bool))); m_doc->setupSignals(); // make sure gets signal from list view // create the command history viewer m_cmdHistoryDock = new QDockWidget(i18n("Co&mmand history"), this); m_cmdHistoryDock->setObjectName(QLatin1String("CmdHistoryDock")); addDockWidget(Qt::LeftDockWidgetArea, m_cmdHistoryDock); m_pQUndoView = new QUndoView(m_cmdHistoryDock); m_pQUndoView->setCleanIcon(Icon_Utils::SmallIcon(Icon_Utils::it_UndoView)); m_pQUndoView->setStack(m_pUndoStack); m_cmdHistoryDock->setWidget(m_pQUndoView); connect(m_cmdHistoryDock, SIGNAL(visibilityChanged(bool)), viewShowCmdHistory, SLOT(setChecked(bool))); m_d->createDiagramsWindow(); #ifdef ENABLE_UML_OBJECTS_WINDOW m_d->createObjectsWindow(); #endif m_d->createStereotypesWindow(); m_d->createWelcomeWindow(); m_debugDock = new QDockWidget(i18n("&Debug"), this); m_debugDock->setObjectName(QLatin1String("DebugDock")); addDockWidget(Qt::LeftDockWidgetArea, m_debugDock); m_debugDock->setWidget(Tracer::instance()); connect(m_debugDock, SIGNAL(visibilityChanged(bool)), viewShowLog, SLOT(setChecked(bool))); // create the log viewer m_logDock = new QDockWidget(i18n("&Log"), this); m_logDock->setObjectName(QLatin1String("LogDock")); addDockWidget(Qt::LeftDockWidgetArea, m_logDock); m_logDock->setWidget(m_d->logWindow); connect(m_logDock, SIGNAL(visibilityChanged(bool)), viewShowLog, SLOT(setChecked(bool))); // create the property viewer //m_propertyDock = new QDockWidget(i18n("&Properties"), this); //m_propertyDock->setObjectName(QLatin1String("PropertyDock")); //addDockWidget(Qt::LeftDockWidgetArea, m_propertyDock); //:TODO: // create the bird's eye view m_birdViewDock = new BirdViewDockWidget(i18n("&Bird's eye view"), this); m_birdViewDock->setObjectName(QLatin1String("BirdViewDock")); addDockWidget(Qt::RightDockWidgetArea, m_birdViewDock); connect(m_birdViewDock, SIGNAL(visibilityChanged(bool)), viewShowBirdView, SLOT(setChecked(bool))); tabifyDockWidget(m_documentationDock, m_cmdHistoryDock); tabifyDockWidget(m_cmdHistoryDock, m_logDock); //tabifyDockWidget(m_cmdHistoryDock, m_propertyDock); //:TODO: tabifyDockWidget(m_logDock, m_debugDock); tabifyDockWidget(m_listDock, m_d->stereotypesWindow); tabifyDockWidget(m_d->stereotypesWindow, m_d->diagramsWindow); #ifdef ENABLE_UML_OBJECTS_WINDOW tabifyDockWidget(m_d->diagramsWindow, m_d->objectsWindow); #endif if (m_d->welcomeWindow) { tabifyDockWidget(m_d->welcomeWindow, m_birdViewDock); m_d->welcomeWindow->raise(); } m_listDock->raise(); } /** * Opens a file specified by commandline option. */ #if QT_VERSION >= 0x050000 void UMLApp::openDocumentFile(const QUrl& url) #else void UMLApp::openDocumentFile(const KUrl& url) #endif { slotStatusMsg(i18n("Opening file...")); m_doc->openDocument(url); fileOpenRecent->addUrl(url); resetStatusMsg(); setCaption(m_doc->url().fileName(), false); enablePrint(true); } /** * Returns a pointer to the current document connected to the * KMainWindow instance. * Used by the View class to access the document object's methods. */ UMLDoc *UMLApp::document() const { return m_doc; } /** * Returns a pointer to the list view. * * @return The listview being used. */ UMLListView* UMLApp::listView() const { return m_listView; } /** * Save general Options like all bar positions and status * as well as the geometry and the recent file list to * the configuration file. */ void UMLApp::saveOptions() { // The Toolbar settings will be handled by the respective classes (KToolBar) KConfigGroup cg(m_config, "toolbar"); toolBar(QLatin1String("mainToolBar"))->saveSettings(cg); KConfigGroup workBarConfig(m_config, "workbar"); m_toolsbar->saveSettings(workBarConfig); fileOpenRecent->saveEntries(m_config->group("Recent Files")); KConfigGroup shortcutConfig(m_config, "Shortcuts"); actionCollection()->writeSettings(&shortcutConfig, false); UmbrelloSettings::setGeometry(size()); Settings::OptionState& optionState = Settings::optionState(); optionState.save(); if(m_doc->url().fileName() == i18n("Untitled")) { UmbrelloSettings::setLastFile(QString()); } else { #if QT_VERSION >= 0x050000 UmbrelloSettings::setLastFile(m_doc->url().toDisplayString()); #else UmbrelloSettings::setLastFile(m_doc->url().prettyUrl()); #endif } UmbrelloSettings::setImageMimeType(imageMimeType()); UmbrelloSettings::setShowDocWindow(m_documentationDock->isVisible()); // CodeGenerator *codegen = getGenerator(); // JavaCodeGenerator *javacodegen = dynamic_cast(codegen); // if (javacodegen) // UmbrelloSettings::setBuildANTDocumentJava(javacodegen->getCreateANTBuildFile()); // now write the basic defaults to config m_commoncodegenpolicy->writeConfig(); #if QT_VERSION >= 0x050000 UmbrelloSettings::self()->save(); #else UmbrelloSettings::self()->writeConfig(); #endif } /** * Read general Options again and initialize all variables * like the recent file list. */ void UMLApp::readOptions() { // bar status settings toolBar(QLatin1String("mainToolBar"))->applySettings(m_config->group("toolbar")); // do config for work toolbar m_toolsbar->applySettings(m_config->group("workbar")); fileOpenRecent->loadEntries(m_config->group("Recent Files")); setImageMimeType(UmbrelloSettings::imageMimeType()); QSize size = UmbrelloSettings::geometry(); if (size.width() == -1 && size.height() == -1) size = QApplication::desktop()->screenGeometry().size(); resize(size); enableUndo(Settings::optionState().generalState.undo); KConfigGroup shortCutConfig(m_config, "Shortcuts"); actionCollection()->readSettings(&shortCutConfig); m_toolsbar->setupActions(); } /** * Saves the window properties for each open window * during session end to the session config file, * including saving the currently opened file by a * temporary filename provided by KApplication. * @see KMainWindow#saveProperties */ void UMLApp::saveProperties(KConfigGroup & cfg) { #if QT_VERSION < 0x050000 DEBUG(DBG_SRC) << "******************** UNUSED?"; Q_UNUSED(cfg); #else if (m_doc->url().fileName() == i18n("Untitled") || m_doc->isModified()) { QUrl url = m_doc->url(); cfg.writePathEntry("filename", url.toString()); cfg.writeEntry("modified", m_doc->isModified()); DEBUG(DBG_SRC) << "Save properties - filenam: " << url << " | modified: " << m_doc->isModified(); // saving to tempfile necessary QTemporaryFile tmpfile(url.toString()); if (tmpfile.open()) { QUrl dest(QUrl::fromLocalFile(tmpfile.fileName())); m_doc->saveDocument(dest); } } #endif } /** * Reads the session config file and restores the * application's state including the last opened files and * documents by reading the temporary files saved by * saveProperties() * @see KMainWindow#readProperties */ void UMLApp::readProperties(const KConfigGroup & cfg) //:TODO: applyMainWindowSettings(const KConfigGroup& config, bool force = false) { #if QT_VERSION < 0x050000 DEBUG(DBG_SRC) << "******************** UNUSED?"; Q_UNUSED(cfg); #else QString filename = cfg.readPathEntry("filename", QString()); QUrl url(filename); bool modified = cfg.readEntry("modified", false); DEBUG(DBG_SRC) << "Read properties - filename: " << url << " | modified: " << modified; if (modified) { QTemporaryFile tmpfile(filename); if (tmpfile.open()) { QUrl _url(QUrl::fromLocalFile(tmpfile.fileName())); m_doc->openDocument(_url); m_doc->setModified(); enablePrint(true); setCaption(_url.fileName() + QStringLiteral(" [*]"), true); } else { enablePrint(false); } } else { if (!filename.isEmpty()) { m_doc->openDocument(url); enablePrint(true); setCaption(url.fileName(), false); } else { enablePrint(false); } } #endif } /** * queryClose is called by KMainWindow on each closeEvent of a * window. Counter to the default implementation (which only * returns true), this calls saveModified() on the document object * to ask if the document shall be saved if Modified; on cancel * the closeEvent is rejected. * @see KMainWindow#queryClose * @see KMainWindow#closeEvent * * @return True if window may be closed. */ bool UMLApp::queryClose() { if (m_doc->saveModified()) { saveOptions(); m_doc->closeDocument(); return true; } return false; } /** * Clears the document in the actual view to reuse it as the new * document. */ void UMLApp::slotFileNew() { slotStatusMsg(i18n("Creating new document...")); if (m_doc->saveModified()) { setDiagramMenuItemsState(false); m_doc->newDocument(); setCaption(m_doc->url().fileName(), false); fileOpenRecent->setCurrentItem(-1); setModified(false); enablePrint(false); } slotUpdateViews(); resetStatusMsg(); } /** * Open a file and load it into the document. */ void UMLApp::slotFileOpen() { slotStatusMsg(i18n("Opening file...")); m_loading = true; if (!m_doc->saveModified()) { // here saving wasn't successful } else { #if QT_VERSION >= 0x050000 QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Open File"), QUrl(), #else KUrl url=KFileDialog::getOpenUrl(KUrl(), #endif i18n("*.xmi *.xmi.tgz *.xmi.tar.bz2 *.mdl *.zargo|All Supported Files (*.xmi, *.xmi.tgz, *.xmi.tar.bz2, *.mdl, *.zargo)\n" "*.xmi|Uncompressed XMI Files (*.xmi)\n" "*.xmi.tgz|Gzip Compressed XMI Files (*.xmi.tgz)\n" "*.xmi.tar.bz2|Bzip2 Compressed XMI Files (*.xmi.tar.bz2)\n" "*.mdl|Rose model files (*.mdl)\n" "*.zargo|Compressed argo Files(*.zargo)\n" ) #if QT_VERSION >= 0x050000 .replace(QLatin1String(","), QLatin1String("")) ); #else ,this, i18n("Open File")); #endif if (!url.isEmpty()) { m_listView->setSortingEnabled(false); if (m_doc->openDocument(url)) { fileOpenRecent->addUrl(url); } enablePrint(true); setCaption(m_doc->url().fileName(), false); m_listView->setSortingEnabled(true); } } slotUpdateViews(); m_loading = false; resetStatusMsg(); } /** * Opens a file from the recent files menu. */ #if QT_VERSION >= 0x050000 void UMLApp::slotFileOpenRecent(const QUrl &url) #else void UMLApp::slotFileOpenRecent(const KUrl &url) #endif { slotStatusMsg(i18n("Opening file...")); m_loading = true; #if QT_VERSION >= 0x050000 QUrl oldUrl = m_doc->url(); #else KUrl oldUrl = m_doc->url(); #endif if (!m_doc->saveModified()) { // here saving wasn't successful } else { if (!m_doc->openDocument(url)) { fileOpenRecent->removeUrl(url); fileOpenRecent->setCurrentItem(-1); } else { fileOpenRecent->addUrl(url); } enablePrint(true); setCaption(m_doc->url().fileName(), false); } m_loading = false; slotUpdateViews(); resetStatusMsg(); } /** * Save a document. */ void UMLApp::slotFileSave() { slotStatusMsg(i18n("Saving file...")); if (m_doc->url().fileName() == i18n("Untitled")) { slotFileSaveAs(); } else { m_doc->saveDocument(m_doc->url()); } if (m_pUndoStack) m_pUndoStack->setClean(); resetStatusMsg(); } /** * Save a document by a new filename. */ bool UMLApp::slotFileSaveAs() { slotStatusMsg(i18n("Saving file with a new filename...")); bool cont = true; #if QT_VERSION >= 0x050000 QUrl url; #else KUrl url; #endif QString ext; while (cont) { #if QT_VERSION >= 0x050000 url = QFileDialog::getSaveFileUrl(this, i18n("Save As"), QUrl(), i18n("*.xmi | XMI File (*.xmi);;" "*.xmi.tgz | Gzip Compressed XMI File (*.xmi.tgz);;" "*.xmi.tar.bz2 | Bzip2 Compressed XMI File (*.xmi.tar.bz2);;" "* | All Files (*)")); #else url = KFileDialog::getSaveUrl(KUrl(), i18n("*.xmi|XMI File\n*.xmi.tgz|Gzip Compressed XMI File\n*.xmi.tar.bz2|Bzip2 Compressed XMI File\n*|All Files"), this, i18n("Save As")); #endif if (url.isEmpty()) { cont = false; } else { if (url.isLocalFile()) { #if QT_VERSION >= 0x050000 QString file = url.toLocalFile(); #else QString file = url.toLocalFile(KUrl::RemoveTrailingSlash); #endif if (QFile::exists(file)) { int want_save = KMessageBox::warningContinueCancel(this, i18n("The file %1 exists.\nDo you wish to overwrite it?", url.toLocalFile()), i18n("Warning"), KGuiItem(i18n("Overwrite"))); if (want_save == KMessageBox::Continue) { cont = false; } } else { cont = false; } } else { cont = false; } } } if (!url.isEmpty()) { bool b = m_doc->saveDocument(url); if (b) { fileOpenRecent->addUrl(url); setCaption(url.fileName(), m_doc->isModified()); resetStatusMsg(); } return b; } else { resetStatusMsg(); return false; } } /** * Asks for saving if the file is modified, then closes the current * file and window. */ void UMLApp::slotFileClose() { slotStatusMsg(i18n("Closing file...")); slotFileNew(); } /** * find text */ void UMLApp::slotFind() { if (!m_d->findDialog.exec()) { UMLApp::app()->document()->writeToStatusBar(i18n("No search term entered")); return; } int count = m_d->findResults.collect(m_d->findDialog.filter(), m_d->findDialog.category(), m_d->findDialog.text()); UMLApp::app()->document()->writeToStatusBar(i18n("'%1': %2 found", m_d->findDialog.text(), count)); slotFindNext(); } /** * Slot for showing next find result */ void UMLApp::slotFindNext() { if (!m_d->findResults.displayNext()) m_d->findResults.displayNext(); } /** * Slot for showing previous find result */ void UMLApp::slotFindPrevious() { if (!m_d->findResults.displayPrevious()) m_d->findResults.displayPrevious(); } /** * Slot for showing a print settings dialog. */ bool UMLApp::slotPrintSettings() { if (m_printSettings) { delete m_printSettings; } m_printSettings = new DiagramPrintPage(0, m_doc); #if QT_VERSION >= 0x050000 QPointer dlg = new QDialog(); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(m_printSettings); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), dlg, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), dlg, SLOT(reject())); layout->addWidget(buttonBox); dlg->setLayout(layout); bool result = dlg->exec() == QDialog::Accepted; // keep settings layout->removeWidget(m_printSettings); #else QPointer dlg = new KDialog(); dlg->setMainWidget(m_printSettings); bool result = dlg->exec() == QDialog::Accepted; // keep settings dlg->setMainWidget(0); #endif m_printSettings->setParent(0); delete dlg; return result; } /** * Print preview */ void UMLApp::slotPrintPreview() { slotStatusMsg(i18n("Print Preview...")); if (!slotPrintSettings()) return; QPointer preview = new QPrintPreviewDialog(m_printer, this); connect(preview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(slotPrintPreviewPaintRequested(QPrinter*))); preview->exec(); delete preview; delete m_printSettings; m_printSettings = 0; resetStatusMsg(); } /** * Print preview painting slot */ void UMLApp::slotPrintPreviewPaintRequested(QPrinter *printer) { m_doc->print(printer, m_printSettings); } /** * Print the current file. */ void UMLApp::slotFilePrint() { slotStatusMsg(i18n("Printing...")); if (!slotPrintSettings()) return; #if QT_VERSION >= 0x050000 QPointer printDialog = new QPrintDialog(m_printer, this); printDialog->setWindowTitle(i18n("Print %1", m_doc->url().toDisplayString())); #else QPointer printDialog = KdePrint::createPrintDialog(m_printer, QList() << m_printSettings, this); printDialog->setWindowTitle(i18n("Print %1", m_doc->url().prettyUrl())); #endif if (printDialog->exec()) { m_doc->print(m_printer, m_printSettings); } delete m_printSettings; m_printSettings = 0; delete printDialog; resetStatusMsg(); } /** * Closes all open windows by calling close() on each * memberList item until the list is empty, then quits the * application. If queryClose() returns false because the * user canceled the saveModified() dialog, the closing * aborts. */ void UMLApp::slotFileQuit() { slotStatusMsg(i18n("Exiting...")); if (m_doc->saveModified()) { saveOptions(); qApp->quit(); } resetStatusMsg(); } /** * Exports the current model to docbook in a subdir of the * current model directory named from the model name. * @todo Let the user chose the destination directory and * name, using network transparency. */ void UMLApp::slotFileExportDocbook() { #if QT_VERSION > 0x050000 QString path = QFileDialog::getExistingDirectory(); #else QString path = KFileDialog::getExistingDirectory(); #endif if (path.isEmpty()) { return; } DocbookGenerator* docbookGenerator = new DocbookGenerator; #if QT_VERSION > 0x050000 docbookGenerator->generateDocbookForProjectInto(QUrl::fromLocalFile(path)); #else docbookGenerator->generateDocbookForProjectInto(path); #endif connect(docbookGenerator, SIGNAL(finished(bool)), docbookGenerator, SLOT(deleteLater())); } /** * Exports the current model to XHTML in a subdir of the * current model directory named from the model name. * @todo Let the user chose the destination directory and * name, using network transparency. */ void UMLApp::slotFileExportXhtml() { #if QT_VERSION > 0x050000 QString path = QFileDialog::getExistingDirectory(); #else QString path = KFileDialog::getExistingDirectory(); #endif if (path.isEmpty()) { return; } if (!m_xhtmlGenerator) { m_xhtmlGenerator = new XhtmlGenerator; } #if QT_VERSION > 0x050000 m_xhtmlGenerator->generateXhtmlForProjectInto(QUrl::fromLocalFile(path)); #else m_xhtmlGenerator->generateXhtmlForProjectInto(path); #endif connect(m_xhtmlGenerator, SIGNAL(finished(bool)), this, SLOT(slotXhtmlDocGenerationFinished(bool))); } /** * Reverts the document back to the state it was prior to the * last action performed by the user. */ void UMLApp::slotEditUndo() { undo(); resetStatusMsg(); } /** * Reverts the document back to the state it was prior to the * last undo. */ void UMLApp::slotEditRedo() { redo(); resetStatusMsg(); } /** * Put the marked text/object into the clipboard and remove * it from the document. */ void UMLApp::slotEditCut() { slotStatusMsg(i18n("Cutting selection...")); //FIXME bug 59774 this fromview isn't very reliable. //when cutting diagrams it is set to true even though it shouldn't be bool fromview = (currentView() && currentView()->umlScene()->selectedCount()); // If not cutting diagram widgets, we did cut on a listview item if (!fromview) { m_listView->setStartedCut(true); } if (editCutCopy(fromview)) { emit sigCutSuccessful(); slotDeleteSelected(); m_doc->setModified(true); } resetStatusMsg(); } /** * Put the marked text/object into the clipboard. */ void UMLApp::slotEditCopy() { slotStatusMsg(i18n("Copying selection to clipboard...")); bool fromview = (currentView() && currentView()->umlScene()->selectedCount()); editCutCopy(fromview); resetStatusMsg(); m_doc->setModified(true); } /** * Paste the clipboard into the document. */ void UMLApp::slotEditPaste() { slotStatusMsg(i18n("Inserting clipboard contents...")); const QMimeData* data = QApplication::clipboard()->mimeData(); UMLClipboard clipboard; setCursor(Qt::WaitCursor); if (!clipboard.paste(data)) { KMessageBox::sorry(this, i18n("Umbrello could not paste the clipboard contents. " "The objects in the clipboard may be of the wrong " "type to be pasted here."), i18n("Paste Error")); } resetStatusMsg(); setCursor(Qt::ArrowCursor); editPaste->setEnabled(false); m_doc->setModified(true); } /** * Changes the statusbar contents for the standard label * permanently, used to indicate current actions. * @param text The text that is displayed in the statusbar */ void UMLApp::slotStatusMsg(const QString &text) { // change status message permanently m_statusBarMessage->setText(text); } /** * Helper method to reset the status bar message. */ void UMLApp::resetStatusMsg() { m_statusBarMessage->setText(i18nc("reset status bar", "Ready.")); } /** * Helper function to create diagram name and the diagram itself. * @param type the type of diagram */ void UMLApp::createDiagram(Uml::DiagramType::Enum type) { QString diagramName = m_doc->createDiagramName(type); if (!diagramName.isEmpty()) executeCommand(new Uml::CmdCreateDiagram(m_doc, type, diagramName)); } /** * Create this view. */ void UMLApp::slotClassDiagram() { createDiagram(Uml::DiagramType::Class); } /** * Create this view. */ void UMLApp::slotObjectDiagram() { createDiagram(Uml::DiagramType::Object); } /** * Create this view. */ void UMLApp::slotSequenceDiagram() { createDiagram(Uml::DiagramType::Sequence); } /** * Create this view. */ void UMLApp::slotCollaborationDiagram() { createDiagram(Uml::DiagramType::Collaboration); } /** * Create this view. */ void UMLApp::slotUseCaseDiagram() { createDiagram(Uml::DiagramType::UseCase); } /** * Create this view. */ void UMLApp::slotStateDiagram() { createDiagram(Uml::DiagramType::State); } /** * Create this view. */ void UMLApp::slotActivityDiagram() { createDiagram(Uml::DiagramType::Activity); } /** * Create this view. */ void UMLApp::slotComponentDiagram() { createDiagram(Uml::DiagramType::Component); } /** * Create this view. */ void UMLApp::slotDeploymentDiagram() { createDiagram(Uml::DiagramType::Deployment); } /** * Create this view. */ void UMLApp::slotEntityRelationshipDiagram() { createDiagram(Uml::DiagramType::EntityRelationship); } /** * Left Alignment */ void UMLApp::slotAlignLeft() { currentView()->umlScene()->alignLeft(); } /** * Right Alignment */ void UMLApp::slotAlignRight() { currentView()->umlScene()->alignRight(); } /** * Top Alignment */ void UMLApp::slotAlignTop() { currentView()->umlScene()->alignTop(); } /** * Bottom Alignment */ void UMLApp::slotAlignBottom() { currentView()->umlScene()->alignBottom(); } /** * Vertical Middle Alignment */ void UMLApp::slotAlignVerticalMiddle() { currentView()->umlScene()->alignVerticalMiddle(); } /** * Horizontal Middle Alignment */ void UMLApp::slotAlignHorizontalMiddle() { currentView()->umlScene()->alignHorizontalMiddle(); } /** * Vertical Distribute Alignment */ void UMLApp::slotAlignVerticalDistribute() { currentView()->umlScene()->alignVerticalDistribute(); } /** * Horizontal Distribute Alignment */ void UMLApp::slotAlignHorizontalDistribute() { currentView()->umlScene()->alignHorizontalDistribute(); } /** * Returns the toolbar being used. * * @return The toolbar being used. */ WorkToolBar* UMLApp::workToolBar() const { return m_toolsbar; } /** * Returns the doc window used. * * @return the doc window being used */ DocWindow* UMLApp::docWindow() const { return m_docWindow; } /** * Returns the log window used. * * @return the log window being used */ QListWidget* UMLApp::logWindow() const { return m_d->logWindow; } /** * Sets whether the program has been modified. * This will change how the program saves/exits. * * @param modified true - modified. */ void UMLApp::setModified(bool modified) { //fileSave->setEnabled(modified); //if anything else needs to be done on a mofication, put it here // printing should be possible whenever there is something to print if (m_loading == false && modified == true && currentView()) { enablePrint(true); } if (m_loading == false) { if (m_doc) { DEBUG(DBG_SRC) << "Modified file=" << m_doc->url().fileName(); setCaption(m_doc->url().fileName(), modified); //add disk icon to taskbar if modified } else { DEBUG(DBG_SRC) << "m_doc is NULL!"; } } } /** * Set whether to allow printing. * It will enable/disable the menu/toolbar options. * * @param enable Set whether to allow printing. */ void UMLApp::enablePrint(bool enable) { filePrint->setEnabled(enable); printPreview->setEnabled(enable); } /** * Initialize Qt's global clipboard support for the application. */ void UMLApp::initClip() { QClipboard* clip = QApplication::clipboard(); connect(clip, SIGNAL(dataChanged()), this, SLOT(slotClipDataChanged())); // Don't poll the X11 clipboard every second. This is a little expensive and resulted // in very annoying umbrello slowdowns / hangs. Qt will notify us about clipboard // changes anyway (see dataChanged() signal above), albeit only when a Qt application // changes the clipboard. Work is in progress to make this work with other toolkits // as well. (pfeiffer) // m_clipTimer = new QTimer(this, "timer"); // m_clipTimer->start(1000, false); // connect(m_clipTimer, SIGNAL(timeout()), this, SLOT(slotClipDataChanged())); m_copyTimer = new QTimer(this); m_copyTimer->setSingleShot(false); m_copyTimer->start(500); connect(m_copyTimer, SIGNAL(timeout()), this, SLOT(slotCopyChanged())); } /** * Returns whether we can decode the given mimesource */ bool UMLApp::canDecode(const QMimeData* mimeData) { QStringList supportedFormats = mimeData->formats(); foreach(const QString &format, supportedFormats) { QByteArray fba = format.toLatin1(); const char* f = fba.constData(); if (!qstrnicmp(f,"application/x-uml-clip", 22)) { //FIXME need to test for clip1, clip2, clip3, clip4 or clip5 //(the only valid clip types) return true; } else if (!qstrnicmp(f,"text/plain", 10)) { return true; } } return false; } /** * Notification of changed clipboard data. */ void UMLApp::slotClipDataChanged() { const QMimeData * data = QApplication::clipboard()->mimeData(); // Pass the MimeSource to the Doc editPaste->setEnabled(data && canDecode(data)); } /** * Slot for enabling cut and copy to clipboard. */ void UMLApp::slotCopyChanged() { if (m_listView->selectedItemsCount() || (currentView() && currentView()->umlScene()->selectedCount())) { editCopy->setEnabled(true); editCut->setEnabled(true); } else { editCopy->setEnabled(false); editCut->setEnabled(false); } } /** * Shows the global preferences dialog. */ void UMLApp::slotPrefs(MultiPageDialogBase::PageType page) { Settings::OptionState& optionState = Settings::optionState(); m_settingsDialog = new SettingsDialog(this, &optionState); m_settingsDialog->setCurrentPage(page); connect(m_settingsDialog, SIGNAL(applyClicked()), this, SLOT(slotApplyPrefs())); if (m_settingsDialog->exec() == QDialog::Accepted && m_settingsDialog->getChangesApplied()) { slotApplyPrefs(); } delete m_settingsDialog; m_settingsDialog = 0; } /** * Commits the changes from the global preferences dialog. */ void UMLApp::slotApplyPrefs() { if (m_settingsDialog) { // we need this to sync both values Settings::OptionState& optionState = Settings::optionState(); enableUndo(optionState.generalState.undo); bool stackBrowsing = (m_layout->indexOf(m_tabWidget) != -1); bool tabBrowsing = optionState.generalState.tabdiagrams; DEBUG(DBG_SRC) << "stackBrowsing=" << stackBrowsing << " / tabBrowsing=" << tabBrowsing; if (stackBrowsing != tabBrowsing) { // Diagram Representation Modified UMLView* currentView; UMLViewList views = m_doc->viewIterator(); if (tabBrowsing) { currentView = static_cast(m_viewStack->currentWidget()); m_layout->removeWidget(m_viewStack); m_viewStack->hide(); foreach (UMLView *view, views) { UMLScene *scene = view->umlScene(); m_viewStack->removeWidget(view); int tabIndex = m_tabWidget->addTab(view, scene->name()); #if QT_VERSION >= 0x050000 m_tabWidget->setTabIcon(tabIndex, QIcon(Icon_Utils::iconSet(scene->type()))); #else m_tabWidget->setTabIcon(tabIndex, KIcon(Icon_Utils::iconSet(scene->type()))); #endif m_tabWidget->setTabToolTip(tabIndex, scene->name()); } m_layout->addWidget(m_tabWidget); m_tabWidget->show(); } else { // stackBrowsing currentView = static_cast(m_tabWidget->currentWidget()); m_layout->removeWidget(m_tabWidget); m_tabWidget->hide(); foreach (UMLView *view, views) { m_tabWidget->removeTab(m_tabWidget->indexOf(view)); m_viewStack->addWidget(view); } m_layout->addWidget(m_viewStack); m_viewStack->show(); } setCurrentView(currentView); } m_doc->settingsChanged(optionState); const QString plStr = m_settingsDialog->getCodeGenerationLanguage(); Uml::ProgrammingLanguage::Enum pl = Uml::ProgrammingLanguage::fromString(plStr); setGenerator(pl); } } /** * Returns the paste state. * * @return True if Paste is enabled. */ bool UMLApp::isPasteState() const { return editPaste->isEnabled(); } /** * Returns the state on Cut/Copy. * * @return True if Cut/Copy is enabled. */ bool UMLApp::isCutCopyState() const { return editCopy->isEnabled(); } /** * Returns the state of undo support. * * @return True if undo is enabled. */ bool UMLApp::isUndoEnabled() { return m_undoEnabled; } /** * Set the state of undo support. * */ void UMLApp::enableUndo(bool enable) { m_undoEnabled = enable; editRedo->setVisible(enable); editUndo->setVisible(enable); viewShowCmdHistory->setVisible(enable); clearUndoStack(); slotShowCmdHistoryView(enable); } /** * Returns the undo state. Is used for popupmenu of a view. * * @return True if Undo is enabled. */ bool UMLApp::isUndoActionEnabled() const { return editUndo->isEnabled(); } /** * Set whether to allow Undo. * It will enable/disable the menu/toolbar options. * * @param enable Set whether to allow printing. */ void UMLApp::enableUndoAction(bool enable) { editUndo->setEnabled(enable); } /** * Returns the redo state. * * @return True if Redo is enabled. Is used for popupmenu of a view. */ bool UMLApp::isRedoActionEnabled() const { return editRedo->isEnabled(); } /** * Set whether to allow Redo. * It will enable/disable the menu/toolbar options. * * @param enable Set whether to allow printing. */ void UMLApp::enableRedoAction(bool enable) { editRedo->setEnabled(enable); } /** * Carries out the cut/copy command with different action performed * depending on if from view or list view. * Cut/Copy are the same. It is up to the caller to delete/cut the selection.. * * If the operation is successful, the signal sigCutSuccessful() is emitted. * * Callers should connect to this signal to know what to do next. */ bool UMLApp::editCutCopy(bool bFromView) { UMLClipboard clipboard; QMimeData * clipdata = 0; // If not from-view, list items are copied. This flag is // used in UMLDragData to determine whether to assign new IDs if (!bFromView) { listView()->setStartedCopy(true); } if ((clipdata = clipboard.copy(bFromView)) != 0) { QClipboard* clip = QApplication::clipboard(); clip->setMimeData(clipdata);//the global clipboard takes ownership of the clipdata memory connect(clip, SIGNAL(dataChanged()), this, SLOT(slotClipDataChanged())); return true; } return false; } /** * Reads from the config file the options state. * Not in @ref readOptions as it needs to be read earlier than some * of the other options, before some items are created. */ void UMLApp::readOptionState() { Settings::OptionState& optionState = Settings::optionState(); #if QT_VERSION >= 0x050000 UmbrelloSettings::self()->load(); #else UmbrelloSettings::self()->readConfig(); #endif optionState.load(); // general config options will be read when created } /** * Call the code viewing assistant on a given UMLClassifier. * * @param classifier Pointer to the classifier to view. */ void UMLApp::viewCodeDocument(UMLClassifier* classifier) { CodeGenerator * currentGen = generator(); if (currentGen && classifier) { AdvancedCodeGenerator *generator = dynamic_cast(currentGen); if (generator) { CodeDocument *cdoc = generator->findCodeDocumentByClassifier(classifier); if (cdoc) { Settings::OptionState& optionState = Settings::optionState(); CodeViewerDialog * dialog = generator->getCodeViewerDialog(this, cdoc, optionState.codeViewerState); dialog->exec(); optionState.codeViewerState = dialog->state(); delete dialog; dialog = 0; } else { // shouldn't happen.. KMessageBox::sorry(0, i18n("Cannot view code until you generate some first."), i18n("Cannot View Code")); } } else { KMessageBox::sorry(0, i18n("Cannot view code from simple code writer."), i18n("Cannot View Code")); } } else { uWarning() << "No CodeGenerator or UMLClassifier given!"; } } /** * Call the refactoring assistant on a classifier. * * @param classifier Pointer to the classifier to refactor. */ void UMLApp::refactor(UMLClassifier* classifier) { if (!m_refactoringAssist) { m_refactoringAssist = new RefactoringAssistant(m_doc, 0, 0, QLatin1String("refactoring_assistant")); } m_refactoringAssist->refactor(classifier); m_refactoringAssist->show(); } /** * Returns the default code generation policy. */ CodeGenerationPolicy *UMLApp::commonPolicy() const { return m_commoncodegenpolicy; } /** * Sets the CodeGenPolicyExt object. */ void UMLApp::setPolicyExt(CodeGenPolicyExt *policy) { m_policyext = policy; } /** * Returns the CodeGenPolicyExt object. */ CodeGenPolicyExt *UMLApp::policyExt() const { return m_policyext; } /** * Auxiliary function for UMLDoc::loadExtensionsFromXMI(): * Return the code generator of the given language if it already * exists; if it does not yet exist then create it and return * the newly created generator. It is the caller's responsibility * to load XMI into the newly created generator. */ CodeGenerator *UMLApp::setGenerator(Uml::ProgrammingLanguage::Enum pl) { if (pl == Uml::ProgrammingLanguage::Reserved) { if (m_codegen) { delete m_codegen; m_codegen = 0; } return 0; } if (m_codegen) { // Do not return a possible preexisting code generator: // if (m_codegen->language() == pl) return m_codegen; // Some languages depend on a new generator instance being created // for each run. delete m_codegen; // ATTENTION! remove all refs to it or its policy first m_codegen = 0; } m_activeLanguage = pl; m_codegen = CodeGenFactory::createObject(pl); updateLangSelectMenu(pl); slotAddDefaultDatatypes(); m_codegen->createDefaultStereotypes(); if (m_policyext) { m_policyext->setDefaults(false); // picks up language specific stuff } return m_codegen; } /** * Gets the appropriate CodeGenerator. * * @return Pointer to the CodeGenerator. */ CodeGenerator* UMLApp::generator() const { return m_codegen; } /** * Determines if SimpleCodeGenerator is active. * * @return true if SimpleCodeGenerator is active. */ bool UMLApp::isSimpleCodeGeneratorActive() { if (m_codegen && dynamic_cast(m_codegen)) { return true; } else { return false; } } /** * Generate code for all classes. */ void UMLApp::slotGenerateAllCode() { if (m_codegen) { m_codegen->writeCodeToFile(); } } /** * Runs the code generation wizard. */ void UMLApp::slotExecGenerationWizard() { QPointer wizard = new CodeGenerationWizard(0 /*classList*/); wizard->exec(); delete wizard; } /** * Slots for connection to the QActions of the m_langSelect menu. */ void UMLApp::setLang_actionscript() { setActiveLanguage(Uml::ProgrammingLanguage::ActionScript); } void UMLApp::setLang_ada() { setActiveLanguage(Uml::ProgrammingLanguage::Ada); } void UMLApp::setLang_cpp() { setActiveLanguage(Uml::ProgrammingLanguage::Cpp); } void UMLApp::setLang_csharp() { setActiveLanguage(Uml::ProgrammingLanguage::CSharp); } void UMLApp::setLang_d() { setActiveLanguage(Uml::ProgrammingLanguage::D); } void UMLApp::setLang_idl() { setActiveLanguage(Uml::ProgrammingLanguage::IDL); } void UMLApp::setLang_java() { setActiveLanguage(Uml::ProgrammingLanguage::Java); } void UMLApp::setLang_javascript() { setActiveLanguage(Uml::ProgrammingLanguage::JavaScript); } void UMLApp::setLang_mysql() { setActiveLanguage(Uml::ProgrammingLanguage::MySQL); } void UMLApp::setLang_pascal() { setActiveLanguage(Uml::ProgrammingLanguage::Pascal); } void UMLApp::setLang_perl() { setActiveLanguage(Uml::ProgrammingLanguage::Perl); } void UMLApp::setLang_php() { setActiveLanguage(Uml::ProgrammingLanguage::PHP); } void UMLApp::setLang_php5() { setActiveLanguage(Uml::ProgrammingLanguage::PHP5); } void UMLApp::setLang_postgresql() { setActiveLanguage(Uml::ProgrammingLanguage::PostgreSQL); } void UMLApp::setLang_python() { setActiveLanguage(Uml::ProgrammingLanguage::Python); } void UMLApp::setLang_ruby() { setActiveLanguage(Uml::ProgrammingLanguage::Ruby); } void UMLApp::setLang_sql() { setActiveLanguage(Uml::ProgrammingLanguage::SQL); } void UMLApp::setLang_tcl() { setActiveLanguage(Uml::ProgrammingLanguage::Tcl); } void UMLApp::setLang_vala() { setActiveLanguage(Uml::ProgrammingLanguage::Vala); } void UMLApp::setLang_xmlschema() { setActiveLanguage(Uml::ProgrammingLanguage::XMLSchema); } #if QT_VERSION >= 0x050000 /** * Called when right clicking on tab widget. * @param point the point where the right mouse button was clicked */ void UMLApp::slotDiagramPopupMenu(const QPoint& point) { QTabBar* tabBar = m_tabWidget->tabBar(); int index = tabBar->tabAt(point); UMLView* view = (UMLView*)m_tabWidget->widget(index); QPoint globalPoint = m_tabWidget->mapToGlobal(point); m_doc->slotDiagramPopupMenu(view, globalPoint); } #endif /** * Set the language for which code will be generated. * * @param pl The name of the language to set */ void UMLApp::setActiveLanguage(Uml::ProgrammingLanguage::Enum pl) { //updateLangSelectMenu(pl); //:TODO:checkit - is already called in setGenerator setGenerator(pl); } /** * Get the language for import and code generation. */ Uml::ProgrammingLanguage::Enum UMLApp::activeLanguage() const { return m_activeLanguage; } /** * Return true if the active language is case sensitive. */ bool UMLApp::activeLanguageIsCaseSensitive() { Uml::ProgrammingLanguage::Enum pl = activeLanguage(); return Uml::ProgrammingLanguage::isCaseSensitive(pl); } /** * Return the target language depedent scope separator. */ QString UMLApp::activeLanguageScopeSeparator() { Uml::ProgrammingLanguage::Enum pl = activeLanguage(); return Uml::ProgrammingLanguage::scopeSeparator(pl); } void UMLApp::slotShowTreeView(bool state) { m_listDock->setVisible(state); viewShowTree->setChecked(state); } void UMLApp::slotShowDebugView(bool state) { m_debugDock->setVisible(state); viewShowDebug->setChecked(state); } void UMLApp::slotShowDocumentationView(bool state) { m_documentationDock->setVisible(state); viewShowDoc->setChecked(state); } void UMLApp::slotShowCmdHistoryView(bool state) { m_cmdHistoryDock->setVisible(state); viewShowCmdHistory->setChecked(state); } void UMLApp::slotShowLogView(bool state) { m_logDock->setVisible(state); viewShowLog->setChecked(state); } void UMLApp::slotShowBirdView(bool state) { m_birdViewDock->setVisible(state); viewShowBirdView->setChecked(state); } /** * Menu selection for clear current view. */ void UMLApp::slotCurrentViewClearDiagram() { currentView()->umlScene()->clearDiagram(); } /** * Menu selection for current view snap to grid property. */ void UMLApp::slotCurrentViewToggleSnapToGrid() { currentView()->umlScene()->toggleSnapToGrid(); viewSnapToGrid->setChecked(currentView()->umlScene()->snapToGrid()); } /** * Menu selection for current view show grid property. */ void UMLApp::slotCurrentViewToggleShowGrid() { currentView()->umlScene()->toggleShowGrid(); viewShowGrid->setChecked(currentView()->umlScene()->isSnapGridVisible()); } /** * Menu selection for exporting current view as an image. */ void UMLApp::slotCurrentViewExportImage() { currentView()->umlScene()->getImageExporter()->exportView(); } /** * Menu selection for exporting all views as images. */ void UMLApp::slotViewsExportImages() { //delete m_printSettings; m_printSettings = new DiagramPrintPage(0, m_doc); DiagramSelectionDialog dlg(m_printSettings); if (dlg.exec() == QDialog::Accepted) m_imageExporterAll->exportViews(m_printSettings); } /** * Menu selection for current view and contained widgets properties. */ void UMLApp::slotCurrentProperties() { UMLWidgetList items = currentView()->umlScene()->selectedWidgets(); if (items.count() == 0) currentView()->showPropertiesDialog(); else if (items.count() == 1) items.at(0)->showPropertiesDialog(); } /** * Sets the state of the view properties menu item. * * @param bState Boolean, true to enable the view properties item. */ void UMLApp::setDiagramMenuItemsState(bool bState) { viewClearDiagram->setEnabled(bState); viewSnapToGrid->setEnabled(bState); viewShowGrid->setEnabled(bState); deleteDiagram->setEnabled(bState); viewExportImage->setEnabled(bState); viewProperties->setEnabled(bState); filePrint->setEnabled(bState); if (currentView()) { viewSnapToGrid->setChecked(currentView()->umlScene()->snapToGrid()); viewShowGrid->setChecked(currentView()->umlScene()->isSnapGridVisible()); } } /** * Register new views (aka diagram) with the GUI so they show up * in the menu. */ void UMLApp::slotUpdateViews() { QMenu* menu = findMenu(QLatin1String(QLatin1String("views"))); if (!menu) { uWarning() << "view menu not found"; return; } menu = findMenu(QLatin1String(QLatin1String("show_view"))); if (!menu) { uWarning() << "show menu not found"; return; } menu->clear(); UMLViewList views = m_doc->viewIterator(); foreach (UMLView *view, views) { menu->addAction(view->umlScene()->name(), view->umlScene(), SLOT(slotShowView())); view->umlScene()->fileLoaded(); } } /** * Import the source files that are in fileList. */ void UMLApp::importFiles(QStringList &fileList, const QString &rootPath) { if (!fileList.isEmpty()) { bool really_visible = !listView()->parentWidget()->visibleRegion().isEmpty(); bool saveState = listView()->parentWidget()->isVisible(); listView()->parentWidget()->setVisible(false); logWindow()->parentWidget()->setVisible(true); logWindow()->clear(); const QString& firstFile = fileList.first(); ClassImport *classImporter = ClassImport::createImporterByFileExt(firstFile); classImporter->setRootPath(rootPath); classImporter->importFiles(fileList); delete classImporter; m_doc->setLoading(false); // Modification is set after the import is made, because the file was modified when adding the classes. // Allowing undo of the whole class importing. I think it eats a lot of memory. // Setting the modification, but without allowing undo. m_doc->setModified(true); listView()->setUpdatesEnabled(true); logWindow()->setUpdatesEnabled(true); listView()->parentWidget()->setVisible(saveState); if (really_visible) m_listDock->raise(); } } /** * Import class menu selection. */ void UMLApp::slotImportClass() { QStringList filters = Uml::ProgrammingLanguage::toExtensions(UMLApp::app()->activeLanguage()); QString f = filters.join(QLatin1String(" ")) + QLatin1String("|") + Uml::ProgrammingLanguage::toExtensionsDescription(UMLApp::app()->activeLanguage()); #if QT_VERSION >= 0x050000 QStringList files = QFileDialog::getOpenFileNames(this, i18n("Select file(s) to import:"), QString(), f); #else QStringList files = KFileDialog::getOpenFileNames(KUrl(), f, this, i18n("Select file(s) to import:")); #endif if (!files.isEmpty()) { importFiles(files); } } /** * @brief getFiles * @param files * @param path * @param filters */ void getFiles(QStringList& files, const QString& path, QStringList& filters) { QDir searchDir(path); if (searchDir.exists()) { foreach (const QFileInfo &file, searchDir.entryList(filters, QDir::Files)) files.append(searchDir.absoluteFilePath(file.fileName())); foreach (const QFileInfo &subDir, searchDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks)) getFiles(files, searchDir.absoluteFilePath(subDir.fileName()), filters); } } /** * Import project menu selection. */ void UMLApp::slotImportProject() { QStringList listFile; #if QT_VERSION >= 0x050000 QString dir = QFileDialog::getExistingDirectory(this, i18n("Select directory to import:")); #else QString dir = KFileDialog::getExistingDirectory(KUrl(),this, i18n("Select directory to import:")); #endif if (!dir.isEmpty()) { QStringList filter = Uml::ProgrammingLanguage::toExtensions(UMLApp::app()->activeLanguage()); getFiles(listFile, dir, filter); importFiles(listFile, dir); } } /** * Runs the code importing wizard. */ void UMLApp::slotImportingWizard() { QPointer wizard = new CodeImportingWizard(); wizard->exec(); delete wizard; } /** * Class wizard menu selection. */ void UMLApp::slotClassWizard() { QPointer dlg = new ClassWizard(m_doc); dlg->exec(); delete dlg; } /** * Calls the active code generator to add its default datatypes. */ void UMLApp::slotAddDefaultDatatypes() { m_doc->addDefaultDatatypes(); } /** * The displayed diagram has changed. */ void UMLApp::slotCurrentViewChanged() { UMLView *view = currentView(); if (view) { connect(view->umlScene(), SIGNAL(sigShowGridToggled(bool)), this, SLOT(slotShowGridToggled(bool))); connect(view->umlScene(), SIGNAL(sigSnapToGridToggled(bool)), this, SLOT(slotSnapToGridToggled(bool))); } } /** * The snap to grid value has been changed. */ void UMLApp::slotSnapToGridToggled(bool gridOn) { viewSnapToGrid->setChecked(gridOn); } /** * The show grid value has been changed. */ void UMLApp::slotShowGridToggled(bool gridOn) { viewShowGrid->setChecked(gridOn); } /** * Select all widgets on the current diagram. */ void UMLApp::slotSelectAll() { currentView()->umlScene()->selectAll(); } /** * Deletes selected widgets or list view items. */ void UMLApp::slotDeleteSelected() { // deleteSelectedWidget grabs DEL key as shortcut, // which prevents routing DEL key through the regular // key press event handler QWidget *f = focusWidget(); if (f == m_listView) { QWidgetAction *o = static_cast(sender()); if (o && o->objectName() == QLatin1String("delete_selected")) { m_listView->slotDeleteSelectedItems(); } return; } if (currentView()) { currentView()->umlScene()->deleteSelection(); } else { uWarning() << " trying to delete widgets when there is no current view (see bug 59774)"; } } /** * Deletes the current diagram. Called from menu action. */ void UMLApp::slotDeleteDiagram() { m_doc->removeDiagram(currentView()->umlScene()->ID()); } #if QT_VERSION >= 0x050000 /** * Close the current diagram. Clicked on tab close button. * @param index widget's index to close */ void UMLApp::slotCloseDiagram(int index) { UMLView* view = (UMLView*)m_tabWidget->widget(index); if (view) { if (view != currentView()) { setCurrentView(view); } m_tabWidget->removeTab(index); view->umlScene()->setIsOpen(false); } } #else /** * Close the current diagram. Clicked on tab close button. * @param tab Widget's tab to close */ void UMLApp::slotCloseDiagram(QWidget* tab) { if (tab) { UMLView* view = (UMLView*)tab; if (view != currentView()) { setCurrentView(view); } m_tabWidget->removeTab(m_tabWidget->indexOf(view)); view->umlScene()->setIsOpen(false); } } #endif /** * Return the default code generation language as configured by KConfig. * If the activeLanguage is not found in the KConfig then use Uml::ProgrammingLanguage::Cpp * as the default. */ Uml::ProgrammingLanguage::Enum UMLApp::defaultLanguage() { Settings::OptionState& optionState = Settings::optionState(); return optionState.generalState.defaultLanguage; } /** * Reads the activeLanguage from the KConfig and calls updateLangSelectMenu() */ void UMLApp::initGenerator() { if (m_codegen) { delete m_codegen; m_codegen = 0; } Uml::ProgrammingLanguage::Enum defLanguage = defaultLanguage(); setActiveLanguage(defLanguage); } /** * Updates the Menu for language selection and sets the * active lanugage. If no active lanugage is found or if it is * not one of the registered languages it tries to fall back * to Cpp */ void UMLApp::updateLangSelectMenu(Uml::ProgrammingLanguage::Enum activeLanguage) { //m_langSelect->clear(); for (int i = 0; i < Uml::ProgrammingLanguage::Reserved; ++i) { m_langAct[i]->setChecked(i == activeLanguage); } } /** * Event handler to receive key press events. */ void UMLApp::keyPressEvent(QKeyEvent *e) { switch(e->key()) { case Qt::Key_Shift: //m_toolsbar->setOldTool(); e->accept(); break; default: e->ignore(); } } /** * Event handler to receive custom events. * It handles events such as exporting all views from command line (in * that case, it executes the exportAllViews method in the event). */ void UMLApp::customEvent(QEvent* e) { if (e->type() == CmdLineExportAllViewsEvent::eventType()) { CmdLineExportAllViewsEvent* exportAllViewsEvent = static_cast(e); exportAllViewsEvent->exportAllViews(); } } /** * Helper method for handling cursor key release events (refactoring). * TODO Move this to UMLWidgetController? */ void UMLApp::handleCursorKeyReleaseEvent(QKeyEvent* e) { // in case we have selected something in the diagram, move it by one pixel // to the direction pointed by the cursor key if (m_view == 0 || !m_view->umlScene()->selectedCount() || e->modifiers() != Qt::AltModifier) { e->ignore(); return; } int dx = 0; int dy = 0; switch (e->key()) { case Qt::Key_Left: dx = -1; break; case Qt::Key_Right: dx = 1; break; case Qt::Key_Up: dy = -1; break; case Qt::Key_Down: dy = 1; break; default: e->ignore(); return; } m_view->umlScene()->moveSelectedBy(dx, dy); // notify about modification only at the first key release of possible sequence of auto repeat key releases, // this reduces the slow down caused by setModified() and makes the cursor moving of widgets smoother if (!e->isAutoRepeat()) { m_doc->setModified(); } e->accept(); } /** * Event handler for key release. */ void UMLApp::keyReleaseEvent(QKeyEvent *e) { switch(e->key()) { case Qt::Key_Backspace: if (!m_docWindow->isTyping()) { m_toolsbar->setOldTool(); } e->accept(); break; case Qt::Key_Escape: m_toolsbar->setDefaultTool(); e->accept(); break; case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: handleCursorKeyReleaseEvent(e); break; default: e->ignore(); } } /** * Calls the UMLDoc method to create a new Document. */ void UMLApp::newDocument() { m_doc->newDocument(); slotUpdateViews(); } /** * Returns the widget used as the parent for UMLViews. * @return The main view widget. */ QWidget* UMLApp::mainViewWidget() { Settings::OptionState& optionState = Settings::optionState(); if (optionState.generalState.tabdiagrams) { return m_tabWidget; } else { return m_viewStack; } } /** * Create bird's view window in a dock widget. */ void UMLApp::createBirdView(UMLView *view) { if (m_birdView) { delete m_birdView; } m_birdView = new BirdView(m_birdViewDock, view); connect(m_birdView, SIGNAL(viewPositionChanged(QPointF)), this, SLOT(slotBirdViewChanged(QPointF))); connect(m_birdViewDock, SIGNAL(sizeChanged(QSize)), m_birdView, SLOT(slotDockSizeChanged(QSize))); } /** * Slot for changes of the bird view's rectangle by moving. * @param delta change value for a move */ void UMLApp::slotBirdViewChanged(const QPointF& delta) { m_birdView->setSlotsEnabled(false); UMLView* view = currentView(); QPointF oldCenter = view->mapToScene(view->viewport()->rect().center()); QPointF newCenter = oldCenter + delta; view->centerOn(newCenter); // DEBUG(DBG_SRC) << "view moved with: " << delta; m_birdView->setSlotsEnabled(true); } /** * Puts this view to the top of the viewStack, i.e. makes it * visible to the user. * * @param view Pointer to the UMLView to push. * @param updateTreeView A false value disables updating of the tree view */ void UMLApp::setCurrentView(UMLView* view, bool updateTreeView) { m_view = view; if (view == 0) { DEBUG(DBG_SRC) << "view is NULL"; docWindow()->reset(); return; } Settings::OptionState optionState = Settings::optionState(); if (optionState.generalState.tabdiagrams) { int tabIndex = m_tabWidget->indexOf(view); if ((tabIndex < 0) && (view->umlScene()->isOpen())) { tabIndex = m_tabWidget->addTab(view, view->umlScene()->name()); #if QT_VERSION >= 0x050000 m_tabWidget->setTabIcon(tabIndex, QIcon(Icon_Utils::iconSet(view->umlScene()->type()))); #else m_tabWidget->setTabIcon(tabIndex, KIcon(Icon_Utils::iconSet(view->umlScene()->type()))); #endif m_tabWidget->setTabToolTip(tabIndex, view->umlScene()->name()); } if (!updateTreeView) #if QT_VERSION >= 0x050000 disconnect(m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(slotTabChanged(int))); #else disconnect(m_tabWidget, SIGNAL(currentChanged(QWidget*)), this, SLOT(slotTabChanged(QWidget*))); #endif m_tabWidget->setCurrentIndex(tabIndex); if (!updateTreeView) #if QT_VERSION >= 0x050000 connect(m_tabWidget, SIGNAL(currentChanged(int)), SLOT(slotTabChanged(int))); #else connect(m_tabWidget, SIGNAL(currentChanged(QWidget*)), SLOT(slotTabChanged(QWidget*))); #endif } else { if (m_viewStack->indexOf(view) < 0) { m_viewStack->addWidget(view); } m_viewStack->setCurrentWidget(view); view->show(); } setZoom(view->zoom()); slotStatusMsg(view->umlScene()->name()); if (updateTreeView) { UMLListViewItem* lvitem = m_listView->findView(view); if (lvitem) { m_listView->setCurrentItem(lvitem); } } DEBUG(DBG_SRC) << "Changed view to" << view->umlScene(); createBirdView(view); } /** * Get the current view. * This may return a null pointer (when no view was previously * specified.) */ UMLView* UMLApp::currentView() const { return m_view; } /** * Sets the default mime type for all diagrams that are exported as images. * @param mimeType the mime type */ void UMLApp::setImageMimeType(const QString& mimeType) { m_imageMimeType = mimeType; } /** * Gets the default mime type for all diagrams that are exported as * images. * @return The default MIME type for images. */ QString UMLApp::imageMimeType() const { return m_imageMimeType; } #if QT_VERSION >= 0x050000 /** * Called when the tab has changed. * @param index the index of the changed tab widget */ void UMLApp::slotTabChanged(int index) { UMLView* view = (UMLView*)m_tabWidget->widget(index); if (view) { m_doc->changeCurrentView(view->umlScene()->ID()); } } #else /** * Called when the tab has changed. * @param tab The changed tab widget */ void UMLApp::slotTabChanged(QWidget* tab) { UMLView* view = (UMLView*)tab; if (view) { m_doc->changeCurrentView(view->umlScene()->ID()); } } #endif /** * Make the tab on the left of the current one the active one. */ void UMLApp::slotChangeTabLeft() { //DEBUG(DBG_SRC) << "currentIndex = " << m_tabWidget->currentIndex() << " of " << m_tabWidget->count(); if (Settings::optionState().generalState.tabdiagrams && m_tabWidget) { m_tabWidget->setCurrentIndex(m_tabWidget->currentIndex() - 1); return; } UMLViewList views = m_doc->viewIterator(); UMLView *currView = m_view; int viewIndex = 0; if ((viewIndex = views.indexOf(currView)) < 0) { uError() << "currView not found in viewlist"; return; } UMLView* prevView = 0; if (viewIndex != 0) { prevView = views.begin()[viewIndex -1 ]; } if ((currView = prevView) != 0) { setCurrentView(currView); } else { setCurrentView(views.last()); } } /** * Make the tab on the right of the current one the active one. */ void UMLApp::slotChangeTabRight() { //DEBUG(DBG_SRC) << "currentIndex = " << m_tabWidget->currentIndex() << " of " << m_tabWidget->count(); if (Settings::optionState().generalState.tabdiagrams && m_tabWidget) { m_tabWidget->setCurrentIndex(m_tabWidget->currentIndex() + 1); return; } UMLViewList views = m_doc->viewIterator(); UMLView *currView = m_view; int viewIndex = 0; if ((viewIndex = views.indexOf(currView)) < 0) { uError() << "currView not found in viewlist"; return; } UMLView* nextView = 0; if (viewIndex < views.count()-1) { nextView = views.begin()[viewIndex + 1]; setCurrentView(nextView); } else setCurrentView(views.first()); } /* for debugging only static void showTabTexts(KTabWidget* tabWidget) { QString out = QLatin1String("tab texts "); for (int i = 0; i < tabWidget->count(); ++i) { out += " <" + tabWidget->tabText(i) + '>'; } DEBUG(DBG_SRC) << out; } */ /** * Move the current tab left. */ void UMLApp::slotMoveTabLeft() { //DEBUG(DBG_SRC) << "currentIndex = " << m_tabWidget->currentIndex() << " of " << m_tabWidget->count(); //showTabTexts(m_tabWidget); int from = m_tabWidget->currentIndex(); int to = -1; if (from > 0) { to = from - 1; } else { to = m_tabWidget->count() - 1; } #if QT_VERSION >= 0x050000 m_tabWidget->tabBar()->moveTab(from, to); #else m_tabWidget->moveTab(from, to); #endif } /** * Move the current tab right. */ void UMLApp::slotMoveTabRight() { //DEBUG(DBG_SRC) << "currentIndex = " << m_tabWidget->currentIndex() << " of " << m_tabWidget->count(); //showTabTexts(m_tabWidget); int from = m_tabWidget->currentIndex(); int to = -1; if (from < m_tabWidget->count() - 1) { to = from + 1; } else { to = 0; } #if QT_VERSION >= 0x050000 m_tabWidget->tabBar()->moveTab(from, to); #else m_tabWidget->moveTab(from, to); #endif } /** * This slot deletes the current XHTML documentation generator as soon as * this one signals that it has finished. * @param status true if successful else false */ void UMLApp::slotXhtmlDocGenerationFinished(bool status) { if (!status) { m_doc->writeToStatusBar(i18n("XHTML Generation failed .")); } delete m_xhtmlGenerator; m_xhtmlGenerator = 0; } +/** + * open file in internal editor + * @param file path to the file to open + * @param startCursor cursor position for selection start + * @param endCursor cursor position for selection end + * @return true file could be loaded + * @return false file could not be loaded + */ +bool UMLApp::slotOpenFileInEditor(const QUrl &file, int startCursor, int endCursor) +{ + return m_d->openFileInEditor(file, startCursor, endCursor); +} + /** * Return the tab widget. */ #if QT_VERSION >= 0x050000 QTabWidget* UMLApp::tabWidget() #else KTabWidget* UMLApp::tabWidget() #endif { return m_tabWidget; } /** * Returns the current text in the status bar. * * @return The text in the status bar. */ QString UMLApp::statusBarMsg() { return m_statusBarMessage->text(); } /** * Removes all entries from the UndoStack and RedoStack and disables the * undo and redo actions. */ void UMLApp::clearUndoStack() { if (m_pUndoStack) m_pUndoStack->clear(); } /** * Undo last command. Is called from popupmenu of a view. */ void UMLApp::undo() { if (!m_pUndoStack) return; if (!isUndoEnabled()) return; DEBUG(DBG_SRC) << m_pUndoStack->undoText() << " [" << m_pUndoStack->count() << "]"; m_pUndoStack->undo(); if (m_pUndoStack->canUndo()) { UMLApp::app()->enableUndoAction(true); } else { UMLApp::app()->enableUndoAction(false); } UMLApp::app()->enableRedoAction(true); } /** * Redo last 'undone' command. Is called from popupmenu of a view. */ void UMLApp::redo() { if (!m_pUndoStack) return; if (!isUndoEnabled()) return; DEBUG(DBG_SRC) << m_pUndoStack->redoText() << " [" << m_pUndoStack->count() << "]"; m_pUndoStack->redo(); if (m_pUndoStack->canRedo()) { UMLApp::app()->enableRedoAction(true); } else { UMLApp::app()->enableRedoAction(false); } UMLApp::app()->enableUndoAction(true); } /** * Execute a command and push it in the stack. */ void UMLApp::executeCommand(QUndoCommand* cmd) { if (!m_pUndoStack) return; if (cmd == 0) return; if (isUndoEnabled()) { m_pUndoStack->push(cmd); DEBUG(DBG_SRC) << cmd->text() << " [" << m_pUndoStack->count() << "]"; UMLApp::app()->enableUndoAction(true); } else { cmd->redo(); delete cmd; } m_doc->setModified(true); } /** * Begin a U/R command macro */ void UMLApp::beginMacro(const QString & text) { if (!m_pUndoStack) return; if (!isUndoEnabled()) { return; } if (m_hasBegunMacro) { return; } m_hasBegunMacro = true; m_pUndoStack->beginMacro(text); } /** * End an U/R command macro */ void UMLApp::endMacro() { if (!m_pUndoStack) return; if (!isUndoEnabled()) { return; } if (m_hasBegunMacro) { m_pUndoStack->endMacro(); } m_hasBegunMacro = false; } /** * Return the config data. */ KConfig* UMLApp::config() { return m_config.data(); } diff --git a/umbrello/uml.h b/umbrello/uml.h index c49cdf402..5d7cffa09 100644 --- a/umbrello/uml.h +++ b/umbrello/uml.h @@ -1,527 +1,528 @@ /*************************************************************************** * 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 * ***************************************************************************/ #ifndef UML_H #define UML_H #include "basictypes.h" #include "multipagedialogbase.h" // kde includes #include #if QT_VERSION < 0x050000 #include #endif #include // qt includes #include #if QT_VERSION >= 0x050000 #include #endif // forward declaration of the UML classes class BirdView; class BirdViewDockWidget; class CodeDocument; class CodeGenerator; class CodeGenerationPolicy; class CodeGenPolicyExt; class DocWindow; class UMLAppPrivate; class UMLClassifier; class UMLDoc; class UMLListView; class UMLView; class WorkToolBar; class SettingsDialog; class UMLViewImageExporterAll; class RefactoringAssistant; class XhtmlGenerator; class StatusBarToolButton; class DiagramPrintPage; // KDE forward declarations class KActionMenu; class KRecentFilesAction; class KToggleAction; class KTabWidget; class KMenu; #if QT_VERSION < 0x050000 class KUndoStack; #endif class KAction; // Qt forward declarations class QStackedWidget; class QToolButton; class QDockWidget; class QVBoxLayout; class QKeyEvent; class QMenu; class QMimeData; class QPrinter; class QUndoCommand; class QUndoView; #if QT_VERSION >= 0x050000 class QUndoStack; #endif class QPushButton; class QLabel; class QListWidget; class QSlider; /** * The base class for UML application windows. It sets up the main * window and reads the config file as well as providing a menubar, toolbar * and statusbar. A list of UMLView instances creates the center views, which are connected * to the window's Doc object. The handling of views is realized with two different widgets: * - stack widget * - tab widget * The current view handling is set as an option. * UMLApp reimplements the methods that KMainWindow provides for main window handling and supports * full session management as well as using KActions. * * @see KMainWindow * @see KApplication * @see KConfig * * @author Paul Hensgen * Bugs and comments to umbrello-devel@kde.org or http://bugs.kde.org */ class UMLApp : public KXmlGuiWindow { Q_OBJECT public: explicit UMLApp(QWidget* parent = 0); ~UMLApp(); static UMLApp* app(); #if QT_VERSION >= 0x050000 void openDocumentFile(const QUrl& url=QUrl()); #else void openDocumentFile(const KUrl& url=KUrl()); #endif void newDocument(); UMLDoc *document() const; UMLListView* listView() const; WorkToolBar* workToolBar() const; DocWindow * docWindow() const; QListWidget *logWindow() const; QCursor defaultCursor(); void setModified(bool _m); void enablePrint(bool enable); bool isPasteState() const; bool isCutCopyState() const; bool isUndoEnabled(); void enableUndo(bool enable); bool isUndoActionEnabled() const; void enableUndoAction(bool enable); bool isRedoActionEnabled() const; void enableRedoAction(bool enable); bool isSimpleCodeGeneratorActive(); void setGenerator(CodeGenerator* gen, bool giveWarning = true); CodeGenerator* setGenerator(Uml::ProgrammingLanguage::Enum pl); CodeGenerator* generator() const; CodeGenerator* createGenerator(); void initGenerator(); void refactor(UMLClassifier* classifier); void viewCodeDocument(UMLClassifier* classifier); void setDiagramMenuItemsState(bool bState); QWidget* mainViewWidget(); void setCurrentView(UMLView* view, bool updateTreeView = true); UMLView* currentView() const; void setImageMimeType(const QString& mimeType); QString imageMimeType() const; bool editCutCopy(bool bFromView); #if QT_VERSION >= 0x050000 QTabWidget *tabWidget(); #else KTabWidget *tabWidget(); #endif QString statusBarMsg(); CodeGenerationPolicy *commonPolicy() const; void setPolicyExt(CodeGenPolicyExt *policy); CodeGenPolicyExt *policyExt() const; void clearUndoStack(); void undo(); void redo(); void executeCommand(QUndoCommand* cmd); void beginMacro(const QString & text); void endMacro(); void setActiveLanguage(Uml::ProgrammingLanguage::Enum pl); Uml::ProgrammingLanguage::Enum activeLanguage() const; Uml::ProgrammingLanguage::Enum defaultLanguage(); bool activeLanguageIsCaseSensitive(); QString activeLanguageScopeSeparator(); KConfig* config(); void importFiles(QStringList& fileList, const QString &rootPath = QString()); protected: virtual void keyPressEvent(QKeyEvent* e); virtual void keyReleaseEvent(QKeyEvent* e); virtual void customEvent(QEvent* e); void handleCursorKeyReleaseEvent(QKeyEvent* e); void saveOptions(); void readOptions(); void initActions(); void initStatusBar(); void initView(); virtual bool queryClose(); virtual void saveProperties(KConfigGroup & cfg); virtual void readProperties(const KConfigGroup & cfg); void updateLangSelectMenu(Uml::ProgrammingLanguage::Enum activeLanguage); public slots: void slotExecGenerationWizard(); void slotImportingWizard(); void slotFileNew(); void slotFileOpen(); #if QT_VERSION >= 0x050000 void slotFileOpenRecent(const QUrl& url); #else void slotFileOpenRecent(const KUrl& url); #endif void slotFileSave(); bool slotFileSaveAs(); void slotFileClose(); bool slotPrintSettings(); void slotPrintPreview(); void slotPrintPreviewPaintRequested(QPrinter *printer); void slotFilePrint(); void slotFileQuit(); void slotFileExportDocbook(); void slotFileExportXhtml(); void slotFind(); void slotFindNext(); void slotFindPrevious(); void slotEditCut(); void slotEditCopy(); void slotEditPaste(); void slotStatusMsg(const QString &text); void slotClassDiagram(); void slotObjectDiagram(); void slotSequenceDiagram(); void slotCollaborationDiagram(); void slotUseCaseDiagram(); void slotStateDiagram(); void slotActivityDiagram(); void slotComponentDiagram(); void slotDeploymentDiagram(); void slotEntityRelationshipDiagram(); void slotAlignLeft(); void slotAlignRight(); void slotAlignTop(); void slotAlignBottom(); void slotAlignVerticalMiddle(); void slotAlignHorizontalMiddle(); void slotAlignVerticalDistribute(); void slotAlignHorizontalDistribute(); void slotClipDataChanged(); void slotCopyChanged(); void slotPrefs(MultiPageDialogBase::PageType page = MultiPageDialogBase::GeneralPage); void slotApplyPrefs(); void slotImportClass(); void slotImportProject(); void slotUpdateViews(); void slotShowTreeView(bool state); void slotShowDebugView(bool state); void slotShowDocumentationView(bool state); void slotShowCmdHistoryView(bool state); void slotShowLogView(bool state); void slotShowBirdView(bool state); void slotCurrentViewClearDiagram(); void slotCurrentViewToggleSnapToGrid(); void slotCurrentViewToggleShowGrid(); void slotCurrentViewExportImage(); void slotViewsExportImages(); void slotCurrentProperties(); void slotClassWizard(); void slotAddDefaultDatatypes(); void slotCurrentViewChanged(); void slotSnapToGridToggled(bool gridOn); void slotShowGridToggled(bool gridOn); void slotSelectAll(); void slotDeleteSelected(); void slotDeleteDiagram(); #if QT_VERSION >= 0x050000 void slotCloseDiagram(int index); #else void slotCloseDiagram(QWidget* tab); #endif void slotGenerateAllCode(); void slotSetZoom(QAction* action); void slotZoomSliderMoved(int value); void slotZoomFit(); void slotZoom100(); void slotZoomOut(); void slotZoomIn(); void slotBirdViewChanged(const QPointF& newCenter); void setupZoomMenu(); void slotEditUndo(); void slotEditRedo(); #if QT_VERSION >= 0x050000 void slotTabChanged(int index); #else void slotTabChanged(QWidget* tab); #endif void slotChangeTabLeft(); void slotChangeTabRight(); void slotMoveTabLeft(); void slotMoveTabRight(); void slotXhtmlDocGenerationFinished(bool status); + bool slotOpenFileInEditor(const QUrl &file, int startCursor = 0, int endCursor = 0); private slots: void setLang_actionscript(); void setLang_ada(); void setLang_cpp(); void setLang_csharp(); void setLang_d(); void setLang_idl(); void setLang_java(); void setLang_javascript(); void setLang_mysql(); void setLang_pascal(); void setLang_perl(); void setLang_php(); void setLang_php5(); void setLang_postgresql(); void setLang_python(); void setLang_ruby(); void setLang_sql(); void setLang_tcl(); void setLang_vala(); void setLang_xmlschema(); #if QT_VERSION >= 0x050000 void slotDiagramPopupMenu(const QPoint& point); #endif private: static UMLApp* s_instance; ///< The last created instance of this class. UMLAppPrivate *m_d; QMenu* findMenu(const QString &name); QAction* createZoomAction(int zoom, int currentZoom); void setZoom(int zoom, bool withView = true); void resetStatusMsg(); void setProgLangAction(Uml::ProgrammingLanguage::Enum pl, const char* name, const char* action); static bool canDecode(const QMimeData* mimeSource); void readOptionState(); void initClip(); void initSavedCodeGenerators(); void createDiagram(Uml::DiagramType::Enum type); void createBirdView(UMLView* view); QMenu* m_langSelect; ///< For selecting the active language. QMenu* m_zoomSelect; ///< Popup menu for zoom selection. Uml::ProgrammingLanguage::Enum m_activeLanguage; ///< Active language. CodeGenerator* m_codegen; ///< Active code generator. CodeGenerationPolicy* m_commoncodegenpolicy; CodeGenPolicyExt* m_policyext; ///< Active policy extension. // Only used for new code generators ({Cpp, Java, Ruby, D}CodeGenerator). KSharedConfigPtr m_config; ///< The configuration object of the application. /** * View is the main widget which represents your working area. * The View class should handle all events of the view widget. * It is kept empty so you can create your view according to your * application's needs by changing the view class. */ QPointer m_view; /** * Doc represents your actual document and is created only once. * It keeps information such as filename and does the loading and * saving of your files. */ UMLDoc* m_doc; UMLListView* m_listView; ///< Listview shows the current open file. QDockWidget* m_mainDock; ///< The widget which shows the diagrams. QDockWidget* m_listDock; ///< Contains the UMLListView tree view. QDockWidget* m_debugDock; ///< Contains the debug DocWindow widget. QDockWidget* m_documentationDock; ///< Contains the documentation DocWindow widget. QDockWidget* m_cmdHistoryDock; ///< Contains the undo/redo viewer widget. QDockWidget* m_propertyDock; ///< Contains the property browser widget. QDockWidget* m_logDock; ///< Contains the log window widget. BirdViewDockWidget* m_birdViewDock;///< Contains the bird's eye view DocWindow* m_docWindow; ///< Documentation window. QListWidget* m_logWindow; ///< Logging window. BirdView* m_birdView; ///< Bird View window QUndoView* m_pQUndoView; ///< Undo / Redo Viewer RefactoringAssistant* m_refactoringAssist; ///< Refactoring assistant. // KAction pointers to enable/disable actions KRecentFilesAction* fileOpenRecent; QAction* printPreview; QAction* filePrint; QAction* editCut; QAction* editCopy; QAction* editPaste; QAction* editUndo; QAction* editRedo; QAction* viewShowTree; QAction* viewShowDebug; QAction* viewShowDoc; QAction* viewShowLog; QAction* viewShowCmdHistory; QAction* viewShowBirdView; KActionMenu* newDiagram; QAction* viewClearDiagram; KToggleAction* viewSnapToGrid; KToggleAction* viewShowGrid; QAction* viewExportImage; QAction* viewProperties; QAction* zoom100Action; QAction* m_langAct[Uml::ProgrammingLanguage::Reserved]; #if QT_VERSION >= 0x050000 QAction* deleteSelectedWidget; QAction* deleteDiagram; #else KAction* deleteSelectedWidget; KAction* deleteDiagram; #endif QToolButton* m_newSessionButton; KMenu* m_diagramMenu; WorkToolBar* m_toolsbar; QTimer* m_clipTimer; QTimer* m_copyTimer; bool m_loading; ///< True if the application is opening an existing document. /** * Shows, and is parent of, all the UMLViews (diagrams) * if tabbed diagrams are not enabled. */ QStackedWidget* m_viewStack; /** * Shows, and is parent of, all the UMLViews (diagrams) * if tabbed diagrams are enabled. */ #if QT_VERSION >= 0x050000 QTabWidget* m_tabWidget; #else KTabWidget* m_tabWidget; #endif /** * Layout supports the dynamic management of the diagram representation (tabbed/stacked) * if tabbed diagrams is enabled it contains m_tabWidget * if tabbed diagrams is disabled it contains m_viewStack */ QVBoxLayout* m_layout; QString m_imageMimeType; ///< Default mime type to use for image export. SettingsDialog* m_settingsDialog; ///< The global UML settings dialog. UMLViewImageExporterAll* m_imageExporterAll; ///< Used to export all the views. /** * Statusbar items */ QLabel* m_zoomValueLbl; QPushButton* m_pZoomOutPB; QPushButton* m_pZoomInPB; StatusBarToolButton* m_pZoomFitSBTB; StatusBarToolButton* m_pZoomFullSBTB; QSlider* m_pZoomSlider; QLabel* m_statusBarMessage; /** * The running XHTML documentation generator. Null when no generation is running. */ XhtmlGenerator* m_xhtmlGenerator; #if QT_VERSION >= 0x050000 QUndoStack* m_pUndoStack; ///< UndoStack used to store actions, to provide Undo/Redo feature. #else KUndoStack* m_pUndoStack; ///< UndoStack used to store actions, to provide Undo/Redo feature. #endif bool m_undoEnabled; ///< Undo enabled flag bool m_hasBegunMacro; ///< Macro creation flag. QPointer m_printSettings; ///< printer diagram settings QPrinter *m_printer; ///< print instance signals: void sigCutSuccessful(); friend class UMLAppPrivate; friend class UMLView; }; #endif // UML_H diff --git a/umbrello/uml1model/artifact.cpp b/umbrello/uml1model/artifact.cpp index f2495c33f..da2dc0aef 100644 --- a/umbrello/uml1model/artifact.cpp +++ b/umbrello/uml1model/artifact.cpp @@ -1,90 +1,105 @@ /*************************************************************************** * 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-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ #include "artifact.h" #include "association.h" #include "clipboard/idchangelog.h" #include +#include + /** * Sets up an Artifact. * @param name The name of the Concept. * @param id The unique id of the Concept. */ UMLArtifact::UMLArtifact(const QString & name, Uml::ID::Type id) : UMLPackage(name, id), m_drawAsType(defaultDraw) { m_BaseType = UMLObject::ot_Artifact; } /** * Standard deconstructor. */ UMLArtifact::~UMLArtifact() { } /** * Make a clone of this object. * @return the cloned object */ UMLObject* UMLArtifact::clone() const { UMLArtifact *clone = new UMLArtifact(); UMLObject::copyInto(clone); return clone; } /** * Creates the UML:Artifact element including its operations, * attributes and templates * @param qDoc the xml document * @param qElement the xml element */ void UMLArtifact::saveToXMI1(QDomDocument& qDoc, QDomElement& qElement) { QDomElement artifactElement = UMLObject::save1(QLatin1String("UML:Artifact"), qDoc); artifactElement.setAttribute(QLatin1String("drawas"), m_drawAsType); qElement.appendChild(artifactElement); } /** * Loads the UML:Artifact element including its operations, * attributes and templates. * @param element the xml element to load * @return the success status of the operation */ bool UMLArtifact::load1(QDomElement& element) { QString drawAs = element.attribute(QLatin1String("drawas"), QLatin1String("0")); m_drawAsType = (Draw_Type)drawAs.toInt(); return true; } /** * Sets m_drawAsType for which method to draw the artifact as. * @param type the draw type */ void UMLArtifact::setDrawAsType(Draw_Type type) { m_drawAsType = type; } /** * Returns the value of m_drawAsType. * @return the value of the draw type attribute */ UMLArtifact::Draw_Type UMLArtifact::getDrawAsType() { return m_drawAsType; } +/** + * Return full path of this artifact including its parent + * @return full path + */ +QString UMLArtifact::fullPath() const +{ + QString path = name(); + for(UMLPackage *p = umlPackage(); p != nullptr && p->umlPackage() != nullptr; p = p->umlPackage()) { + path.insert(0, p->name() + QLatin1Char('/')); + } + return QDir::toNativeSeparators(path); +} + diff --git a/umbrello/uml1model/artifact.h b/umbrello/uml1model/artifact.h index 0a75d08f8..f7c5e73c6 100644 --- a/umbrello/uml1model/artifact.h +++ b/umbrello/uml1model/artifact.h @@ -1,66 +1,68 @@ /*************************************************************************** * 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-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ #ifndef ARTIFACT_H #define ARTIFACT_H #include "package.h" /** * This class contains the non-graphical information required for a UML * Artifact. * This class inherits from @ref UMLCanvasObject which contains most of the * information. * * @short Non-graphical information for a Artifact. * @author Jonathan Riddell * @see UMLCanvasObject * Bugs and comments to umbrello-devel@kde.org or http://bugs.kde.org */ class UMLArtifact : public UMLPackage { Q_OBJECT public: /** * Artifacts can be drawn using one of several icons. */ enum Draw_Type { defaultDraw, file, library, table }; explicit UMLArtifact(const QString & name = QString(), Uml::ID::Type id = Uml::ID::None); virtual ~UMLArtifact(); virtual UMLObject* clone() const; void saveToXMI1(QDomDocument & qDoc, QDomElement & qElement); void setDrawAsType(Draw_Type type); Draw_Type getDrawAsType(); + QString fullPath() const; + protected: bool load1(QDomElement & element); private: /** * Artifacts can be drawn as one of several different icons, * this value choosing how to draw them. */ Draw_Type m_drawAsType; }; #endif diff --git a/umbrello/umlappprivate.cpp b/umbrello/umlappprivate.cpp index 64f051e4c..b1848e8d7 100644 --- a/umbrello/umlappprivate.cpp +++ b/umbrello/umlappprivate.cpp @@ -1,133 +1,171 @@ /*************************************************************************** * 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 * ***************************************************************************/ #include "umlappprivate.h" #include "debug_utils.h" #include /** * Find welcome.html file for displaying in the welcome window. * * @return path to welcome file or empty if not found */ QString UMLAppPrivate::findWelcomeFile() { QStringList dirList; // from build dir dirList.append(QCoreApplication::applicationDirPath() + QLatin1String("/../doc/apphelp")); // determine path from installation #if QT_VERSION > 0x050000 QString name = QLocale().name(); QStringList lang = name.split(QLatin1Char('_')); QStringList langList; langList.append(lang[0]); if (lang.size() > 1) langList.append(name); // from custom install foreach(const QString &lang, langList) { dirList.append(QCoreApplication::applicationDirPath() + QString(QLatin1String("/../share/doc/HTML/%1/umbrello/apphelp")).arg(lang)); } dirList.append(QCoreApplication::applicationDirPath() + QLatin1String("/../share/doc/HTML/en/umbrello/apphelp")); QStringList locations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); // from real installation foreach(const QString &location, locations) { foreach(const QString &lang, langList) { dirList.append(QString(QLatin1String("%1/doc/HTML/%2/umbrello/apphelp")).arg(location).arg(lang)); } dirList.append(QString(QLatin1String("%1/doc/HTML/en/umbrello/apphelp")).arg(location)); } #else KLocale *local = KGlobal::locale(); QString lang = local->language(); // from custom install dirList.append(QCoreApplication::applicationDirPath() + QString(QLatin1String("/../share/doc/HTML/%1/umbrello/apphelp")).arg(lang)); dirList.append(QCoreApplication::applicationDirPath() + QLatin1String("/../share/doc/HTML/en/umbrello/apphelp")); // /usr/share/doc/kde dirList.append(KStandardDirs::installPath("html") + lang + QLatin1String("/umbrello/apphelp")); #endif foreach(const QString &dir, dirList) { QString filePath = dir + QLatin1String("/index.cache.bz2"); QFileInfo fi(filePath); if (fi.exists()) { uDebug() << "searching for" << filePath << "found"; return filePath; } else uDebug() << "searching for" << filePath; } return QString(); } /** * Read welcome file for displaying in the welcome window. * * This method also patches out some unrelated stuff from * the html file intended or being displayed with khelpcenter. * * @return html content of welcome file */ QString UMLAppPrivate::readWelcomeFile(const QString &file) { QString html; if (file.endsWith(QLatin1String(".cache.bz2"))) { QIODevice *d = KFilterDev::deviceForFile(file); if (!d->open(QIODevice::ReadOnly)) { uError() << "could not open archive " << file; return QString(); } QByteArray data = d->readAll(); html = QString::fromUtf8(data); d->close(); } else { QFile f(file); if (!f.open(QIODevice::ReadOnly)) return QString(); QTextStream in(&f); html = in.readAll(); } if (html.isEmpty()) { uError() << "Empty welcome page loaded" << file; return QString(); } html.replace(QLatin1String(""),QLatin1String("")); html.replace(QLatin1String(""),QLatin1String("")); //#define WITH_HEADER #ifndef WITH_HEADER html.replace(QLatin1String("
= 0x050000 QString path; QStringList locations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); foreach(const QString &l, locations) { QString a = QString(QLatin1String("%1/doc/HTML/en/")).arg(l); QFileInfo fi(a); if (fi.exists()) { path = a; break; } } #else QString path = KStandardDirs::installPath("html") + QLatin1String("en/"); #endif QUrl url(QUrl::fromLocalFile(path)); QByteArray a = url.toEncoded(); html.replace(QLatin1String("help:/"), QString::fromLocal8Bit(a)); #endif return html; } + +bool UMLAppPrivate::openFileInEditor(const QUrl &file, int startCursor, int endCursor) +{ + if (editor == nullptr) { + uError() << "could not get editor instance, which indicates an installation problem, see for kate[4]-parts package"; + return false; + } + + if (file.isLocalFile()) { + QFileInfo fi(file.toLocalFile()); + if (!fi.exists()) + return false; + } + + if (!editorWindow) { + editorWindow = new QDockWidget(QLatin1String("Editor")); + parent->addDockWidget(Qt::RightDockWidgetArea, editorWindow); + } + + if (document) { + editorWindow->setWidget(0); + delete view; + delete document; + } + document = editor->createDocument(0); + view = document->createView(parent); + view->document()->openUrl(file); + view->document()->setReadWrite(false); + if (startCursor != endCursor) + view->setCursorPosition(KTextEditor::Cursor(startCursor, endCursor)); + KTextEditor::ConfigInterface *iface = qobject_cast(view); + if(iface) + iface->setConfigValue(QString::fromLatin1("line-numbers"), true); + + editorWindow->setWidget(view); + editorWindow->setVisible(true); + return true; +} diff --git a/umbrello/umlappprivate.h b/umbrello/umlappprivate.h index 8a2eb8792..a3f500dff 100644 --- a/umbrello/umlappprivate.h +++ b/umbrello/umlappprivate.h @@ -1,231 +1,204 @@ /*************************************************************************** * 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 * ***************************************************************************/ #ifndef UMLAPPPRIVATE_H #define UMLAPPPRIVATE_H // app includes #include "cmds.h" #include "debug_utils.h" #include "finddialog.h" #include "findresults.h" #include "uml.h" #include "umldoc.h" #include "diagramswindow.h" #include "objectswindow.h" #include "stereotypeswindow.h" // kde includes #include #if QT_VERSION < 0x050000 #include #endif #include #include #include #include #if QT_VERSION < 0x050000 #include #endif #include // qt includes #include #include #include #include #include #include class QWidget; /** * Class UMLAppPrivate holds private class members/methods * to reduce the size of the public class and to speed up * recompiling. * The migration to this class is not complete yet. **/ class UMLAppPrivate : public QObject { Q_OBJECT public: UMLApp *parent; FindDialog findDialog; FindResults findResults; QListWidget *logWindow; ///< Logging window. KToggleAction *viewDiagramsWindow; KToggleAction *viewObjectsWindow; KToggleAction *viewStereotypesWindow; KToggleAction *viewWelcomeWindow; DiagramsWindow *diagramsWindow; ObjectsWindow *objectsWindow; StereotypesWindow *stereotypesWindow; QDockWidget *welcomeWindow; QDockWidget *editorWindow; KTextEditor::Editor *editor; KTextEditor::View *view; KTextEditor::Document *document; explicit UMLAppPrivate(UMLApp *_parent) : parent(_parent), findDialog(_parent), viewDiagramsWindow(0), viewObjectsWindow(0), viewStereotypesWindow(0), viewWelcomeWindow(0), diagramsWindow(0), objectsWindow(0), stereotypesWindow(0), welcomeWindow(0), editorWindow(0), view(0), document(0) { #if QT_VERSION >= 0x050000 editor = KTextEditor::Editor::instance(); #else editor = KTextEditor::EditorChooser::editor(); #endif logWindow = new QListWidget; connect(logWindow, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(slotLogWindowItemDoubleClicked(QListWidgetItem *))); } ~UMLAppPrivate() { delete diagramsWindow; delete editorWindow; delete logWindow; delete objectsWindow; delete stereotypesWindow; delete welcomeWindow; } + bool openFileInEditor(const QUrl &file, int startCursor=0, int endCursor=0); + public slots: void slotLogWindowItemDoubleClicked(QListWidgetItem *item) { - if (editor == nullptr) { - uError() << "could not get editor instance, which indicates an installation problem, see for kate[4]-parts package"; - return; - } - QStringList columns = item->text().split(QChar::fromLatin1(':')); - QFileInfo file(columns[0]); - if (!file.exists()) - return; - - if (!editorWindow) { - editorWindow = new QDockWidget(QLatin1String("Editor")); - parent->addDockWidget(Qt::RightDockWidgetArea, editorWindow); - } - - if (document) { - editorWindow->setWidget(0); - delete view; - delete document; - } - document = editor->createDocument(0); - view = document->createView(parent); - view->document()->openUrl(QUrl::fromLocalFile(columns[0])); - view->document()->setReadWrite(false); - view->setCursorPosition(KTextEditor::Cursor(columns[1].toInt()-1,columns[2].toInt())); - KTextEditor::ConfigInterface *iface = qobject_cast(view); - if(iface) - iface->setConfigValue(QString::fromLatin1("line-numbers"), true); - - editorWindow->setWidget(view); - editorWindow->setVisible(true); + openFileInEditor(QUrl::fromLocalFile(columns[0]), columns[1].toInt()-1, columns[2].toInt()); } void createDiagramsWindow() { // create the tree viewer diagramsWindow = new DiagramsWindow(i18n("&Diagrams"), parent); parent->addDockWidget(Qt::LeftDockWidgetArea, diagramsWindow); viewDiagramsWindow = parent->actionCollection()->add(QLatin1String("view_show_diagrams")); connect(viewDiagramsWindow, SIGNAL(triggered(bool)), diagramsWindow, SLOT(setVisible(bool))); } void createObjectsWindow() { // create the object window objectsWindow = new ObjectsWindow(i18n("&UML Objects"), parent); parent->addDockWidget(Qt::LeftDockWidgetArea, objectsWindow); viewObjectsWindow = parent->actionCollection()->add(QLatin1String("view_show_objects")); connect(viewObjectsWindow, SIGNAL(triggered(bool)), objectsWindow, SLOT(setVisible(bool))); } void createStereotypesWindow() { // create the tree viewer stereotypesWindow = new StereotypesWindow(i18n("&Stereotypes"), parent); parent->addDockWidget(Qt::LeftDockWidgetArea, stereotypesWindow); viewStereotypesWindow = parent->actionCollection()->add(QLatin1String("view_show_stereotypes")); connect(viewStereotypesWindow, SIGNAL(triggered(bool)), stereotypesWindow, SLOT(setVisible(bool))); } void createWelcomeWindow() { QString file = findWelcomeFile(); if (file.isEmpty()) return; QString html = readWelcomeFile(file); if (html.isEmpty()) return; // qDebug() << html; welcomeWindow = new QDockWidget(i18n("Welcome"), parent); welcomeWindow->setObjectName(QLatin1String("WelcomeDock")); QWebView *view = new QWebView; view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); view->setContextMenuPolicy(Qt::NoContextMenu); connect(view, SIGNAL(linkClicked(const QUrl)), this, SLOT(slotWelcomeWindowLinkClicked(const QUrl))); view->setHtml(html); view->show(); welcomeWindow->setWidget(view); parent->addDockWidget(Qt::RightDockWidgetArea, welcomeWindow); viewWelcomeWindow = parent->actionCollection()->add(QLatin1String("view_show_welcome")); connect(viewWelcomeWindow, SIGNAL(triggered(bool)), welcomeWindow, SLOT(setVisible(bool))); } void slotWelcomeWindowLinkClicked(const QUrl &url) { //qDebug() << url; if (url.scheme() == QLatin1String("mailto") || url.scheme().startsWith(QLatin1String("http"))) { QDesktopServices::openUrl(url); return; } QStringList list = url.toString().split(QLatin1Char('-')); list.removeLast(); QString key; foreach(const QString s, list) { QString a = s; a[0] = a[0].toUpper(); key.append(a); } Uml::DiagramType::Enum type = Uml::DiagramType::fromString(key); if (type == Uml::DiagramType::Undefined) return; QString diagramName = UMLApp::app()->document()->createDiagramName(type); if (!diagramName.isEmpty()) UMLApp::app()->executeCommand(new Uml::CmdCreateDiagram(UMLApp::app()->document(), type, diagramName)); } private: QString findWelcomeFile(); QString readWelcomeFile(const QString &file); }; #endif diff --git a/umbrello/umllistview.cpp b/umbrello/umllistview.cpp index a68cab27d..ecaa0c7a2 100644 --- a/umbrello/umllistview.cpp +++ b/umbrello/umllistview.cpp @@ -1,2883 +1,2895 @@ /*************************************************************************** * 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 "umllistview.h" // app includes #include "actor.h" #include "classifier.h" #include "cmds.h" #include "debug_utils.h" #include "dialog_utils.h" #include "package.h" #include "folder.h" #include "component.h" #include "node.h" #include "artifact.h" #include "enum.h" #include "enumliteral.h" #include "entity.h" #include "category.h" #include "docwindow.h" #include "layoutgenerator.h" #include "umllistviewpopupmenu.h" #include "template.h" #include "operation.h" #include "attribute.h" #include "entityattribute.h" #include "instance.h" #include "instanceattribute.h" #include "uniqueconstraint.h" #include "foreignkeyconstraint.h" #include "checkconstraint.h" #include "uml.h" #include "umlclipboard.h" #include "umldoc.h" #include "umllistviewitemlist.h" #include "umllistviewitem.h" #include "umlscene.h" #include "umlview.h" #include "umlviewimageexporter.h" #include "usecase.h" #include "model_utils.h" #include "models/diagramsmodel.h" #include "optionstate.h" #include "uniqueid.h" #include "idchangelog.h" #include "umldragdata.h" #include "classpropertiesdialog.h" #include "umlattributedialog.h" #include "umlentityattributedialog.h" #include "umloperationdialog.h" #include "umltemplatedialog.h" #include "umluniqueconstraintdialog.h" #include "umlforeignkeyconstraintdialog.h" #include "umlcheckconstraintdialog.h" #include "object_factory.h" // kde includes #if QT_VERSION < 0x050000 #include #endif #include #include #if QT_VERSION < 0x050000 #include #endif // qt includes #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #include #include #include #include #include #include #include #include DEBUG_REGISTER(UMLListView) /** * Constructs the tree view. * * @param parent The parent to this. */ UMLListView::UMLListView(QWidget *parent) : QTreeWidget(parent), m_rv(0), m_datatypeFolder(0), m_settingsFolder(0), m_doc(UMLApp::app()->document()), m_bStartedCut(false), m_bStartedCopy(false), m_bCreatingChildObject(false), m_dragStartPosition(QPoint()), m_dragCopyData(0) { // setup list view setAcceptDrops(true); //setDropVisualizer(false); //setItemsMovable(true); //setItemsRenameable(true); setSelectionMode(ExtendedSelection); setFocusPolicy(Qt::StrongFocus); setDragEnabled(true); //setColumnWidthMode(0, Manual); //setDefaultRenameAction(Accept); //setResizeMode(LastColumn); //header()->setClickEnabled(true); //add columns and initial items //addColumn(m_doc->name()); setSortingEnabled(true); sortByColumn(0, Qt::AscendingOrder); setEditTriggers(QAbstractItemView::EditKeyPressed); for (int i = 0; i < Uml::ModelType::N_MODELTYPES; ++i) { m_lv[i] = 0; } //setup slots/signals connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(slotCollapsed(QTreeWidgetItem*))); connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(slotExpanded(QTreeWidgetItem*))); connect(UMLApp::app(), SIGNAL(sigCutSuccessful()), this, SLOT(slotCutSuccessful())); connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(slotItemSelectionChanged())); } /** * Standard destructor. */ UMLListView::~UMLListView() { clean(); // m_lv delete m_datatypeFolder; delete m_settingsFolder; delete m_rv; } /** * Sets the title. * @param column column in which to write * @param text the text to write */ void UMLListView::setTitle(int column, const QString &text) { headerItem()->setText(column, text); } /** * Handler for item selection changed signals. */ void UMLListView::slotItemSelectionChanged() { UMLListViewItem* currItem = static_cast(currentItem()); if (currItem && currItem->isSelected()) { DEBUG(DBG_SRC) << "UMLListView selection changed to" << currItem->text(0); // Update current view to selected object's view if (Model_Utils::typeIsDiagram(currItem->type())) { // If the user navigates to a diagram, load the diagram just like what // would happen when clicking on it (includes saving/showing the documentation) m_doc->changeCurrentView(currItem->ID()); } else { // If the user navigates to any other item, save the current object's // documentation and show selected object's documentation UMLApp::app()->docWindow()->showDocumentation(currItem->umlObject(), true); } } } /** * Event handler for the tool tip event. * Works only for operations to show the signature. */ bool UMLListView::event(QEvent *e) { if (e->type() == QEvent::ToolTip) { QHelpEvent *helpEvent = static_cast(e); UMLListViewItem * item = static_cast(itemAt(helpEvent->pos())); if (item) { QToolTip::showText(helpEvent->globalPos(), item->toolTip()); } else { QToolTip::hideText(); e->ignore(); } return true; } return QTreeWidget::event(e); } /** * Handler for mouse press events. * @param me the mouse event */ void UMLListView::mousePressEvent(QMouseEvent *me) { UMLView *currentView = UMLApp::app()->currentView(); Q_ASSERT(currentView); UMLScene *scene = currentView->umlScene(); Q_ASSERT(scene); scene->clearSelected(); if (me->modifiers() != Qt::ShiftModifier) clearSelection(); // Get the UMLListViewItem at the point where the mouse pointer was pressed UMLListViewItem * item = static_cast(itemAt(me->pos())); if (item) { DEBUG(DBG_SRC) << "QMouseEvent on" << UMLListViewItem::toString(item->type()); } else { DEBUG(DBG_SRC) << "QMouseEvent on empty space"; } const Qt::MouseButton button = me->button(); if (!item || (button != Qt::RightButton && button != Qt::LeftButton)) { UMLApp::app()->docWindow()->updateDocumentation(true); return; } if (button == Qt::LeftButton) { UMLObject *o = item->umlObject(); if (o) UMLApp::app()->docWindow()->showDocumentation(o, false); else UMLApp::app()->docWindow()->updateDocumentation(true); m_dragStartPosition = me->pos(); } QTreeWidget::mousePressEvent(me); } /** * Handler for mouse move events. * @param me the mouse event */ void UMLListView::mouseMoveEvent(QMouseEvent* me) { if (!(me->buttons() & Qt::LeftButton)) { DEBUG(DBG_SRC) << "not LeftButton (no action)"; return; } if ((me->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { DEBUG(DBG_SRC) << "pos change since dragStart is below startDragDistance threshold (no action)"; return; } DEBUG(DBG_SRC) << "initiating drag"; // Store a copy of selected list items in case the user // will ctrl-drag (basically just copy/paste) an item // // The QDrag mime data is used for moving items onto the diagram // or internally in the tree view UMLClipboard clipboard; if ((m_dragCopyData = clipboard.copy(false)) == 0) { // This should never happen, this is just like using ctrl+c on the list view item uError() << "Unable to obtain mime data for copy-drag operation"; } QDrag* drag = new QDrag(this); drag->setMimeData(getDragData()); drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction); } /** * Handler for mouse release event. * @param me the mouse event */ void UMLListView::mouseReleaseEvent(QMouseEvent *me) { if (me->button() != Qt::LeftButton) { QTreeWidget::mouseReleaseEvent(me); return; } UMLListViewItem *item = static_cast(itemAt(me->pos())); if (item == 0 || !Model_Utils::typeIsDiagram(item->type())) { QTreeWidget::mouseReleaseEvent(me); return; } // Switch to diagram on mouse release - not on mouse press // because the user might intend a drag-to-note. m_doc->changeCurrentView(item->ID()); UMLView *view = m_doc->findView(item->ID()); if (view && view->umlScene()) UMLApp::app()->docWindow()->showDocumentation(view->umlScene(), false); QTreeWidget::mouseReleaseEvent(me); } /** * Handler for key press events. * @param ke the key event */ void UMLListView::keyPressEvent(QKeyEvent *ke) { QTreeWidget::keyPressEvent(ke); // let parent handle it const int k = ke->key(); if (k == Qt::Key_Delete || k == Qt::Key_Backspace) { slotDeleteSelectedItems(); } else if (k == Qt::Key_F3) { // prelimary support for layout generator LayoutGenerator r; if (!r.generate(UMLApp::app()->currentView()->umlScene())) return; r.apply(UMLApp::app()->currentView()->umlScene()); } } /** * Called when a right mouse button menu has an item selected. * @param action the selected action * @param position the position of the menu on the diagram (only used for multi selection "Show") */ void UMLListView::slotMenuSelection(QAction* action, const QPoint &position) { UMLListViewItem * currItem = static_cast(currentItem()); if (!currItem) { DEBUG(DBG_SRC) << "Invoked without currently selectedItem!"; return; } UMLListViewItem::ListViewType lvt = currItem->type(); ListPopupMenu::MenuType menuType = ListPopupMenu::typeFromAction(action); switch (menuType) { case ListPopupMenu::mt_Activity_Diagram: addNewItem(currItem, UMLListViewItem::lvt_Activity_Diagram); break; case ListPopupMenu::mt_Class_Diagram: addNewItem(currItem, UMLListViewItem::lvt_Class_Diagram); break; case ListPopupMenu::mt_Collaboration_Diagram: addNewItem(currItem, UMLListViewItem::lvt_Collaboration_Diagram); break; case ListPopupMenu::mt_Component_Diagram: addNewItem(currItem, UMLListViewItem::lvt_Component_Diagram); break; case ListPopupMenu::mt_Deployment_Diagram: addNewItem(currItem, UMLListViewItem::lvt_Deployment_Diagram); break; case ListPopupMenu::mt_EntityRelationship_Diagram: addNewItem(currItem, UMLListViewItem::lvt_EntityRelationship_Diagram); break; case ListPopupMenu::mt_Sequence_Diagram: addNewItem(currItem, UMLListViewItem::lvt_Sequence_Diagram); break; case ListPopupMenu::mt_State_Diagram: addNewItem(currItem, UMLListViewItem::lvt_State_Diagram); break; case ListPopupMenu::mt_UseCase_Diagram: addNewItem(currItem, UMLListViewItem::lvt_UseCase_Diagram); break; case ListPopupMenu::mt_Class: addNewItem(currItem, UMLListViewItem::lvt_Class); break; case ListPopupMenu::mt_Package: addNewItem(currItem, UMLListViewItem::lvt_Package); break; case ListPopupMenu::mt_Subsystem: addNewItem(currItem, UMLListViewItem::lvt_Subsystem); break; case ListPopupMenu::mt_Component: addNewItem(currItem, UMLListViewItem::lvt_Component); break; case ListPopupMenu::mt_Port: if (Settings::optionState().generalState.uml2) addNewItem(currItem, UMLListViewItem::lvt_Port); break; case ListPopupMenu::mt_Node: addNewItem(currItem, UMLListViewItem::lvt_Node); break; case ListPopupMenu::mt_Artifact: addNewItem(currItem, UMLListViewItem::lvt_Artifact); break; case ListPopupMenu::mt_Interface: addNewItem(currItem, UMLListViewItem::lvt_Interface); break; case ListPopupMenu::mt_Enum: addNewItem(currItem, UMLListViewItem::lvt_Enum); break; case ListPopupMenu::mt_EnumLiteral: addNewItem(currItem, UMLListViewItem::lvt_EnumLiteral); break; case ListPopupMenu::mt_Template: addNewItem(currItem, UMLListViewItem::lvt_Template); break; case ListPopupMenu::mt_Entity: addNewItem(currItem, UMLListViewItem::lvt_Entity); break; case ListPopupMenu::mt_Category: addNewItem(currItem, UMLListViewItem::lvt_Category); break; case ListPopupMenu::mt_DisjointSpecialisation: { UMLCategory* catObj = currItem->umlObject()->asUMLCategory(); catObj->setType(UMLCategory::ct_Disjoint_Specialisation); } break; case ListPopupMenu::mt_OverlappingSpecialisation: { UMLCategory* catObj = currItem->umlObject()->asUMLCategory(); catObj->setType(UMLCategory::ct_Overlapping_Specialisation); } break; case ListPopupMenu::mt_Union: { UMLCategory* catObj = currItem->umlObject()->asUMLCategory(); catObj->setType(UMLCategory::ct_Union); } break; case ListPopupMenu::mt_Datatype: addNewItem(currItem, UMLListViewItem::lvt_Datatype); break; case ListPopupMenu::mt_Actor: addNewItem(currItem, UMLListViewItem::lvt_Actor); break; case ListPopupMenu::mt_UseCase: addNewItem(currItem, UMLListViewItem::lvt_UseCase); break; case ListPopupMenu::mt_Attribute: addNewItem(currItem, UMLListViewItem::lvt_Attribute); break; case ListPopupMenu::mt_EntityAttribute: addNewItem(currItem, UMLListViewItem::lvt_EntityAttribute); break; case ListPopupMenu::mt_InstanceAttribute: addNewItem(currItem, UMLListViewItem::lvt_InstanteAttribute); break; case ListPopupMenu::mt_Operation: addNewItem(currItem, UMLListViewItem::lvt_Operation); break; case ListPopupMenu::mt_UniqueConstraint: addNewItem(currItem, UMLListViewItem::lvt_UniqueConstraint); break; case ListPopupMenu::mt_PrimaryKeyConstraint: addNewItem(currItem, UMLListViewItem::lvt_PrimaryKeyConstraint); break; case ListPopupMenu::mt_ForeignKeyConstraint: addNewItem(currItem, UMLListViewItem::lvt_ForeignKeyConstraint); break; case ListPopupMenu::mt_CheckConstraint: addNewItem(currItem, UMLListViewItem::lvt_CheckConstraint); break; case ListPopupMenu::mt_Import_Class: UMLApp::app()->slotImportClass(); break; case ListPopupMenu::mt_Import_Project: UMLApp::app()->slotImportProject(); break; case ListPopupMenu::mt_Expand_All: expandAll(currItem); break; case ListPopupMenu::mt_Collapse_All: collapseAll(currItem); break; case ListPopupMenu::mt_Export_Image: { const Uml::ID::Type id = currItem->ID(); UMLView *view = m_doc->findView(id); if (view) { if (view->umlScene()) view->umlScene()->getImageExporter()->exportView(); else uError() << "ListPopupMenu::mt_Export_Image: view " << Uml::ID::toString(id) << " umlScene() is NULL"; } else { uError() << "ListPopupMenu::mt_Export_Image: m_doc->findView(" << Uml::ID::toString(id) << " returns NULL"; } } break; case ListPopupMenu::mt_Externalize_Folder: { UMLListViewItem *current = static_cast(currentItem()); UMLFolder *modelFolder = current->umlObject()->asUMLFolder(); if (modelFolder == 0) { uError() << "modelFolder is 0"; return; } // configure & show the file dialog #if QT_VERSION >= 0x050000 const QString rootDir(m_doc->url().adjusted(QUrl::RemoveFilename).path()); QPointer fileDialog = new QFileDialog(this, i18n("Externalize Folder"), rootDir, QLatin1String("*.xml")); #else const QString rootDir(m_doc->url().directory()); QPointer fileDialog = new KFileDialog(rootDir, QLatin1String("*.xml"), this); fileDialog->setCaption(i18n("Externalize Folder")); fileDialog->setOperationMode(KFileDialog::Other); #endif // set a sensible default filename QString defaultFilename = current->text(0).toLower(); defaultFilename.replace(QRegExp(QLatin1String("\\W+")), QLatin1String("_")); defaultFilename.append(QLatin1String(".xml")); // default extension #if QT_VERSION >= 0x050000 fileDialog->selectFile(defaultFilename); QList selURL; if (fileDialog->exec() == QDialog::Accepted) { selURL = fileDialog->selectedUrls(); } #else fileDialog->setSelection(defaultFilename); KUrl selURL; if (fileDialog->exec() == QDialog::Accepted) { selURL = fileDialog->selectedUrl(); } #endif delete fileDialog; if (selURL.isEmpty()) return; #if QT_VERSION >= 0x050000 QString path = selURL[0].toLocalFile(); #else QString path = selURL.toLocalFile(); #endif QString fileName = path; if (fileName.startsWith(rootDir)) { fileName.remove(rootDir); } else { KMessageBox::error( 0, i18n("Folder %1 must be relative to the main model directory, %2.", path, rootDir), i18n("Path Error")); return; } QFile file(path); // Warn if file exists. if (file.exists()) { KMessageBox::error( 0, i18n("File %1 already exists!\nThe existing file will be overwritten.", fileName), i18n("File Exist")); } // Test if file is writable. if (file.open(QIODevice::WriteOnly)) { file.close(); } else { KMessageBox::error( 0, i18n("There was a problem saving file: %1", fileName), i18n("Save Error")); return; } modelFolder->setFolderFile(fileName); // Recompute text of the folder QString folderText = current->text(0); folderText.remove(QRegExp(QLatin1String("\\s*\\(.*$"))); folderText.append(QLatin1String(" (") + fileName + QLatin1Char(')')); current->setText(folderText); break; } case ListPopupMenu::mt_Internalize_Folder: { UMLListViewItem *current = static_cast(currentItem()); UMLFolder *modelFolder = current->umlObject()->asUMLFolder(); if (modelFolder == 0) { uError() << "modelFolder is 0"; return; } modelFolder->setFolderFile(QString()); // Recompute text of the folder QString folderText = current->text(0); folderText.remove(QRegExp(QLatin1String("\\s*\\(.*$"))); current->setText(folderText); break; } case ListPopupMenu::mt_Model: { QString name = m_doc->name(); bool ok = Dialog_Utils::askName(i18n("Enter Model Name"), i18n("Enter the new name of the model:"), name); if (ok) { setTitle(0, name); m_doc->setName(name); } break; } + case ListPopupMenu::mt_Open_File: { + UMLListViewItem *current = static_cast(currentItem()); + UMLArtifact *artifact = current->umlObject()->asUMLArtifact(); + if (artifact == nullptr) { + uError() << "artifact is 0"; + return; + } + QUrl file = QUrl::fromLocalFile(artifact->fullPath()); + UMLApp::app()->slotOpenFileInEditor(file); + break; + } + case ListPopupMenu::mt_Rename: edit(currentIndex()); break; case ListPopupMenu::mt_Delete: deleteItem(currItem); break; case ListPopupMenu::mt_Show: // first check if we are on a diagram if (!Model_Utils::typeIsDiagram(lvt)) { UMLObject * object = currItem->umlObject(); if (!object) { uError() << "UMLObjet of ... is null! Doing nothing."; return; } QList findResults; if (Model_Utils::typeIsCanvasWidget(lvt)) { UMLViewList views = m_doc->viewIterator(); foreach (UMLView *view, views) { foreach(UMLWidget *widget, view->umlScene()->widgetList()) { if (object == widget->umlObject()) { findResults.append(widget); } } } } if (findResults.size() == 0) { break; } UMLWidget *selectedResult = 0; if (findResults.size() > 1) { QMenu menu(this); int i = 0; foreach(UMLWidget *w, findResults) { QAction *action = menu.addAction(w->umlScene()->name() + QLatin1Char(':') + w->name()); action->setData(i++); } QAction *action = menu.exec(position); if (action) { selectedResult = findResults.at(action->data().toInt()); } } else { selectedResult = findResults.first(); } if (!selectedResult) { break; } UMLView *view = selectedResult->umlScene()->activeView(); selectedResult->umlScene()->setIsOpen(true); view->setZoom(100); if (UMLApp::app()->currentView() != view) { UMLApp::app()->setCurrentView(view, false); } view->centerOn(selectedResult->scenePos()); selectedResult->setSelected(true); } break; case ListPopupMenu::mt_Properties: if (Model_Utils::typeIsProperties(lvt)) { UMLApp::app()->slotPrefs(Model_Utils::convert_LVT_PT(lvt)); return; } else if (Model_Utils::typeIsDiagram(lvt)) { UMLView * pView = m_doc->findView(currItem->ID()); if (pView) { UMLApp::app()->docWindow()->updateDocumentation(false); pView->showPropertiesDialog(); UMLApp::app()->docWindow()->showDocumentation(pView->umlScene(), true); } return; } { // ok, we are on another object, so find out on which one UMLObject * object = currItem->umlObject(); if (!object) { uError() << "UMLObject of ... is null! Doing nothing."; return; } object->showPropertiesDialog(); } break; case ListPopupMenu::mt_Logical_Folder: addNewItem(currItem, UMLListViewItem::lvt_Logical_Folder); break; case ListPopupMenu::mt_UseCase_Folder: addNewItem(currItem, UMLListViewItem::lvt_UseCase_Folder); break; case ListPopupMenu::mt_Component_Folder: addNewItem(currItem, UMLListViewItem::lvt_Component_Folder); break; case ListPopupMenu::mt_Deployment_Folder: addNewItem(currItem, UMLListViewItem::lvt_Deployment_Folder); break; case ListPopupMenu::mt_EntityRelationship_Folder: addNewItem(currItem, UMLListViewItem::lvt_EntityRelationship_Folder); break; case ListPopupMenu::mt_Cut: m_bStartedCut = true; m_bStartedCopy = false; UMLApp::app()->slotEditCut(); break; case ListPopupMenu::mt_Copy: m_bStartedCut = false; m_bStartedCopy = true; UMLApp::app()->slotEditCopy(); break; case ListPopupMenu::mt_Paste: UMLApp::app()->slotEditPaste(); break; case ListPopupMenu::mt_Clone: UMLApp::app()->slotEditCopy(); UMLApp::app()->slotEditPaste(); break; case ListPopupMenu::mt_ChangeToClass: { UMLClassifier* o = currItem->umlObject()->asUMLClassifier(); o->setStereotypeCmd(QString()); currItem->updateObject(); } break; case ListPopupMenu::mt_ChangeToPackage: { UMLClassifier* o = currItem->umlObject()->asUMLClassifier(); o->setStereotypeCmd(QString()); o->setBaseType(UMLObject::ot_Package); currItem->updateObject(); } break; case ListPopupMenu::mt_Undefined: // We got signalled for a menu action, but that menu action was not // defined in ListPopupMenu. This is the case for "create diagram" // actions which are defined and handled in UMLApp. This is fine, // ignore them without warning. break; default: uError() << "unknown type" << menuType; break; }//end switch } /** * Find the parent folder for a diagram. * If the currently selected item in the list view is a folder * then that folder is returned as the parent. * * @param dt The Diagram_Type of the diagram. * The type will only be used if there is no currently * selected item, or if the current item is not a folder. * In that case the root folder which is suitable for the * Diagram_Type is returned. * @return Pointer to the parent UMLListViewItem for the diagram. */ UMLListViewItem *UMLListView::findFolderForDiagram(Uml::DiagramType::Enum dt) { UMLListViewItem *p = static_cast(currentItem()); if (p && Model_Utils::typeIsFolder(p->type()) && !Model_Utils::typeIsRootView(p->type())) { return p; } switch (dt) { case Uml::DiagramType::UseCase: p = m_lv[Uml::ModelType::UseCase]; break; case Uml::DiagramType::Component: p = m_lv[Uml::ModelType::Component]; break; case Uml::DiagramType::Deployment: p = m_lv[Uml::ModelType::Deployment]; break; case Uml::DiagramType::EntityRelationship: p = m_lv[Uml::ModelType::EntityRelationship]; break; default: p = m_lv[Uml::ModelType::Logical]; break; } return p; } /** * Creates a new item to represent a new diagram. * @param id the id of the new diagram */ void UMLListView::slotDiagramCreated(Uml::ID::Type id) { if (findItem(id)) { uDebug() << "list view item " << Uml::ID::toString(id) << " already exists"; return; } UMLView *v = m_doc->findView(id); if (v) { UMLScene *scene = v->umlScene(); if (scene) { const Uml::DiagramType::Enum dt = scene->type(); UMLListViewItem* p = findUMLObject(scene->folder()); UMLListViewItem* item = new UMLListViewItem(p, scene->name(), Model_Utils::convert_DT_LVT(dt), id); item->setSelected(true); UMLApp::app()->docWindow()->showDocumentation(scene, false); } } else { uError() << "UmlDoc::findView(" << Uml::ID::toString(id) << ") returns NULL"; } } /** * Determine the parent ListViewItem given an UMLObject. * * @param object Pointer to the UMLObject for which to look up the parent. * @return Pointer to the parent UMLListViewItem chosen. * Returns NULL on error (no parent could be determined.) */ UMLListViewItem* UMLListView::determineParentItem(UMLObject* object) const { UMLListViewItem* parentItem = 0; UMLPackage* pkg = 0; UMLListViewItem* current = (UMLListViewItem*) currentItem(); UMLListViewItem::ListViewType lvt = UMLListViewItem::lvt_Unknown; if (current) lvt = current->type(); UMLObject::ObjectType t = object->baseType(); switch (t) { case UMLObject::ot_Attribute: case UMLObject::ot_Operation: case UMLObject::ot_Template: case UMLObject::ot_EnumLiteral: case UMLObject::ot_EntityAttribute: case UMLObject::ot_InstanceAttribute: case UMLObject::ot_UniqueConstraint: case UMLObject::ot_ForeignKeyConstraint: case UMLObject::ot_CheckConstraint: //this will be handled by childObjectAdded return 0; break; case UMLObject::ot_Association: case UMLObject::ot_Role: case UMLObject::ot_Stereotype: return 0; // currently no representation in list view break; default: pkg = object->umlPackage(); if (pkg) { UMLListViewItem* pkgItem = findUMLObject(pkg); if (pkgItem == 0) uError() << "could not find parent package " << pkg->name(); else parentItem = pkgItem; } else if ((lvt == UMLListViewItem::lvt_UseCase_Folder && (t == UMLObject::ot_Actor || t == UMLObject::ot_UseCase)) || (lvt == UMLListViewItem::lvt_Component_Folder && t == UMLObject::ot_Component) || (lvt == UMLListViewItem::lvt_Deployment_Folder && t == UMLObject::ot_Node) || (lvt == UMLListViewItem::lvt_EntityRelationship_Folder && t == UMLObject::ot_Entity)) { parentItem = current; } else if (t == UMLObject::ot_Datatype) { parentItem = m_datatypeFolder; } else { Uml::ModelType::Enum guess = Model_Utils::guessContainer(object); parentItem = m_lv[guess]; } break; } return parentItem; } /** * Return true if the given ObjectType permits child items. * A "child item" is anything that qualifies as a UMLClassifierListItem, * e.g. operations and attributes of classifiers. */ bool UMLListView::mayHaveChildItems(UMLObject::ObjectType type) { bool retval = false; switch (type) { case UMLObject::ot_Class: case UMLObject::ot_Interface: case UMLObject::ot_Instance: case UMLObject::ot_Enum: case UMLObject::ot_Entity: // CHECK: more? retval = true; break; default: break; } return retval; } /** * Creates a new list view item and connects the appropriate signals/slots. * @param object the newly created object */ void UMLListView::slotObjectCreated(UMLObject* object) { if (m_bCreatingChildObject) { // @todo eliminate futile signal traffic // e.g. we get here thru various indirections from // ClassifierListPage::slot{Up, Down}Clicked() return; } if (object->baseType() == UMLObject::ot_Association) return; UMLListViewItem* newItem = findUMLObject(object); if (newItem) { DEBUG(DBG_SRC) << object->name() << ", type=" << newItem->type() << ", id=" << Uml::ID::toString(object->id()) << ": item already exists."; Icon_Utils::IconType icon = Model_Utils::convert_LVT_IT(newItem->type()); newItem->setIcon(icon); return; } UMLListViewItem* parentItem = 0; UMLPackage *p = object->umlPackage(); if (p) { parentItem = findUMLObject(p); if (parentItem == 0) parentItem = determineParentItem(object); } else { uWarning() << object->name() << " : umlPackage not set on object"; parentItem = determineParentItem(object); } if (parentItem == 0) return; UMLObject::ObjectType type = object->baseType(); connectNewObjectsSlots(object); const UMLListViewItem::ListViewType lvt = Model_Utils::convert_OT_LVT(object); QString name = object->name(); if (type == UMLObject::ot_Folder) { UMLFolder *f = object->asUMLFolder(); QString folderFile = f->folderFile(); if (!folderFile.isEmpty()) name.append(QLatin1String(" (") + folderFile + QLatin1Char(')')); } newItem = new UMLListViewItem(parentItem, name, lvt, object); if (mayHaveChildItems(type)) { UMLClassifier *c = object->asUMLClassifier(); UMLClassifierListItemList cListItems = c->getFilteredList(UMLObject::ot_UMLObject); foreach(UMLClassifierListItem *cli, cListItems) childObjectAdded(cli, c); } if (m_doc->loading()) return; scrollToItem(newItem); newItem->setOpen(true); clearSelection(); newItem->setSelected(true); UMLApp::app()->docWindow()->showDocumentation(object, false); } /** * Connect some signals into slots in the list view for newly created UMLObjects. */ void UMLListView::connectNewObjectsSlots(UMLObject* object) { UMLObject::ObjectType type = object->baseType(); switch (type) { case UMLObject::ot_Class: case UMLObject::ot_Interface: { UMLClassifier *c = object->asUMLClassifier(); connect(c, SIGNAL(attributeAdded(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(c, SIGNAL(attributeRemoved(UMLClassifierListItem*)), this, SLOT(childObjectRemoved(UMLClassifierListItem*))); connect(c, SIGNAL(operationAdded(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(c, SIGNAL(operationRemoved(UMLClassifierListItem*)), this, SLOT(childObjectRemoved(UMLClassifierListItem*))); connect(c, SIGNAL(templateAdded(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(c, SIGNAL(templateRemoved(UMLClassifierListItem*)), this, SLOT(childObjectRemoved(UMLClassifierListItem*))); connect(object, SIGNAL(modified()), this, SLOT(slotObjectChanged())); } break; case UMLObject::ot_Instance:{ UMLInstance *c = object->asUMLInstance(); connect(c, SIGNAL(attributeAdded(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(c, SIGNAL(attributeRemoved(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(object, SIGNAL(modified()), this, SLOT(slotObjectChanged())); } break; case UMLObject::ot_Enum: { UMLEnum *e = object->asUMLEnum(); connect(e, SIGNAL(enumLiteralAdded(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(e, SIGNAL(enumLiteralRemoved(UMLClassifierListItem*)), this, SLOT(childObjectRemoved(UMLClassifierListItem*))); } connect(object, SIGNAL(modified()), this, SLOT(slotObjectChanged())); break; case UMLObject::ot_Entity: { UMLEntity *ent = object->asUMLEntity(); connect(ent, SIGNAL(entityAttributeAdded(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(ent, SIGNAL(entityAttributeRemoved(UMLClassifierListItem*)), this, SLOT(childObjectRemoved(UMLClassifierListItem*))); connect(ent, SIGNAL(entityConstraintAdded(UMLClassifierListItem*)), this, SLOT(childObjectAdded(UMLClassifierListItem*))); connect(ent, SIGNAL(entityConstraintRemoved(UMLClassifierListItem*)), this, SLOT(childObjectRemoved(UMLClassifierListItem*))); } connect(object, SIGNAL(modified()), this, SLOT(slotObjectChanged())); break; case UMLObject::ot_Datatype: case UMLObject::ot_Attribute: case UMLObject::ot_Operation: case UMLObject::ot_Template: case UMLObject::ot_EnumLiteral: case UMLObject::ot_EntityAttribute: case UMLObject::ot_InstanceAttribute: case UMLObject::ot_UniqueConstraint: case UMLObject::ot_ForeignKeyConstraint: case UMLObject::ot_CheckConstraint: case UMLObject::ot_Package: case UMLObject::ot_Actor: case UMLObject::ot_UseCase: case UMLObject::ot_Component: case UMLObject::ot_Port: case UMLObject::ot_Artifact: case UMLObject::ot_Node: case UMLObject::ot_Folder: case UMLObject::ot_Category: connect(object, SIGNAL(modified()), this, SLOT(slotObjectChanged())); break; case UMLObject::ot_UMLObject: case UMLObject::ot_Association: case UMLObject::ot_Stereotype: break; default: uWarning() << "unknown type in connectNewObjectsSlots"; break; } } /** * Calls updateObject() on the item representing the sending object * no parameters, uses sender() to work out which object called the slot. */ void UMLListView::slotObjectChanged() { if (m_doc->loading()) { //needed for class wizard return; } UMLObject* obj = const_cast(dynamic_cast(sender())); UMLListViewItem* item = findUMLObject(obj); if (item) { item->updateObject(); } } /** * Adds a new operation, attribute or template item to a classifier. * @param obj the child object */ void UMLListView::childObjectAdded(UMLClassifierListItem* obj) { UMLClassifier *parent = const_cast(dynamic_cast(sender())); childObjectAdded(obj, parent); } /** * Adds a new operation, attribute or template item to a classifier, identical to * childObjectAdded(obj) but with an explicit parent. * @param child the child object * @param parent the parent object */ void UMLListView::childObjectAdded(UMLClassifierListItem* child, UMLClassifier* parent) { if (m_bCreatingChildObject) return; const QString text = child->toString(Uml::SignatureType::SigNoVis); UMLListViewItem *childItem = 0; UMLListViewItem *parentItem = findUMLObject(parent); if (parentItem == 0) { DEBUG(DBG_SRC) << child->name() << ": parent " << parent->name() << " does not yet exist, creating it now."; const UMLListViewItem::ListViewType lvt = Model_Utils::convert_OT_LVT(parent); parentItem = new UMLListViewItem(m_lv[Uml::ModelType::Logical], parent->name(), lvt, parent); } else { childItem = parentItem->findChildObject(child); } if (childItem) { childItem->setText(text); } else { const UMLListViewItem::ListViewType lvt = Model_Utils::convert_OT_LVT(child); childItem = new UMLListViewItem(parentItem, text, lvt, child); if (! m_doc->loading()) { scrollToItem(childItem); clearSelection(); childItem->setSelected(true); } connectNewObjectsSlots(child); } } /** * Deletes the list view item. * @param obj the object to remove */ void UMLListView::childObjectRemoved(UMLClassifierListItem* obj) { UMLClassifier *parent = const_cast(dynamic_cast(sender())); UMLListViewItem *parentItem = findUMLObject(parent); if (parentItem == 0) { uError() << obj->name() << ": cannot find parent UMLListViewItem"; return; } parentItem->deleteChildItem(obj); } /** * Renames a diagram in the list view * @param id the id of the renamed diagram */ void UMLListView::slotDiagramRenamed(Uml::ID::Type id) { UMLListViewItem* item; UMLView* v = m_doc->findView(id); if ((item = findView(v)) == 0) { uError() << "UMLDoc::findView(" << Uml::ID::toString(id) << ") returns 0"; return; } item->setText(v->umlScene()->name()); } /** * Sets the document this is associated with. This is important as * this is required as to set up the callbacks. * * @param doc The document to associate with this class. */ void UMLListView::setDocument(UMLDoc *doc) { if (m_doc && m_doc != doc) { //disconnect signals from old doc and reset view } m_doc = doc; connect(m_doc, SIGNAL(sigDiagramCreated(Uml::ID::Type)), this, SLOT(slotDiagramCreated(Uml::ID::Type))); connect(m_doc, SIGNAL(sigDiagramRemoved(Uml::ID::Type)), this, SLOT(slotDiagramRemoved(Uml::ID::Type))); connect(m_doc, SIGNAL(sigDiagramRenamed(Uml::ID::Type)), this, SLOT(slotDiagramRenamed(Uml::ID::Type))); connect(m_doc, SIGNAL(sigObjectCreated(UMLObject*)), this, SLOT(slotObjectCreated(UMLObject*))); connect(m_doc, SIGNAL(sigObjectRemoved(UMLObject*)), this, SLOT(slotObjectRemoved(UMLObject*))); } /** * Disconnects signals and removes the list view item. * @param object the object about to be removed */ void UMLListView::slotObjectRemoved(UMLObject* object) { if (m_doc->loading() && !m_doc->importing()) { //needed for class wizard but not when importing return; } disconnect(object, SIGNAL(modified()), this, SLOT(slotObjectChanged())); UMLListViewItem* item = findItem(object->id()); delete item; UMLApp::app()->docWindow()->updateDocumentation(true); } /** * Removes the item representing a diagram. * @param id the id of the diagram */ void UMLListView::slotDiagramRemoved(Uml::ID::Type id) { UMLListViewItem* item = findItem(id); delete item; UMLApp::app()->docWindow()->updateDocumentation(true); } /** * */ UMLDragData* UMLListView::getDragData() { UMLListViewItemList itemsSelected = selectedItems(); UMLListViewItemList list; foreach(UMLListViewItem* item, itemsSelected) { UMLListViewItem::ListViewType type = item->type(); if (!Model_Utils::typeIsCanvasWidget(type) && !Model_Utils::typeIsDiagram(type) && !Model_Utils::typeIsClassifierList(type)) { return 0; } list.append(item); } UMLDragData *t = new UMLDragData(list, this); return t; } /** * This methods looks for a object in a folder an its subfolders recursive. * @param folder The folder entry of the list view. * @param obj The object to be found in the folder. * @return The object if found else a NULL pointer. */ UMLListViewItem * UMLListView::findUMLObjectInFolder(UMLListViewItem* folder, UMLObject* obj) { for (int i=0; i < folder->childCount(); ++i) { UMLListViewItem *item = folder->childItem(i); switch (item->type()) { case UMLListViewItem::lvt_Actor : case UMLListViewItem::lvt_UseCase : case UMLListViewItem::lvt_Class : case UMLListViewItem::lvt_Package : case UMLListViewItem::lvt_Subsystem : case UMLListViewItem::lvt_Component : case UMLListViewItem::lvt_Port : case UMLListViewItem::lvt_Node : case UMLListViewItem::lvt_Artifact : case UMLListViewItem::lvt_Interface : case UMLListViewItem::lvt_Datatype : case UMLListViewItem::lvt_Enum : case UMLListViewItem::lvt_Entity : case UMLListViewItem::lvt_Category: if (item->umlObject() == obj) return item; break; case UMLListViewItem::lvt_Logical_Folder : case UMLListViewItem::lvt_UseCase_Folder : case UMLListViewItem::lvt_Component_Folder : case UMLListViewItem::lvt_Deployment_Folder : case UMLListViewItem::lvt_EntityRelationship_Folder : case UMLListViewItem::lvt_Datatype_Folder : { UMLListViewItem *temp = findUMLObjectInFolder(item, obj); if (temp) return temp; } default: break; } } return 0; } /** * Find an UMLObject in the listview. * * @param p Pointer to the object to find in the list view. * @return Pointer to the UMLObject found or NULL if not found. */ UMLListViewItem * UMLListView::findUMLObject(const UMLObject *p) const { UMLListViewItem *item = m_rv; UMLListViewItem *testItem = item->findUMLObject(p); if (testItem) return testItem; return 0; } /** * Changes the icon for the given UMLObject to the given icon. */ void UMLListView::changeIconOf(UMLObject *o, Icon_Utils::IconType to) { UMLListViewItem *item = findUMLObject(o); if (item) item->setIcon(to); } /** * Searches through the tree for the item which represents the diagram given. * @param v the diagram to search for * @return the item which represents the diagram */ UMLListViewItem* UMLListView::findView(UMLView* v) { if (!v) { uWarning() << "returning 0 - param is 0."; return 0; } UMLListViewItem* item; Uml::DiagramType::Enum dType = v->umlScene()->type(); UMLListViewItem::ListViewType type = Model_Utils::convert_DT_LVT(dType); Uml::ID::Type id = v->umlScene()->ID(); if (dType == Uml::DiagramType::UseCase) { item = m_lv[Uml::ModelType::UseCase]; } else if (dType == Uml::DiagramType::Component) { item = m_lv[Uml::ModelType::Component]; } else if (dType == Uml::DiagramType::Deployment) { item = m_lv[Uml::ModelType::Deployment]; } else if (dType == Uml::DiagramType::EntityRelationship) { item = m_lv[Uml::ModelType::EntityRelationship]; } else { item = m_lv[Uml::ModelType::Logical]; } for (int i=0; i < item->childCount(); i++) { UMLListViewItem* foundItem = recursiveSearchForView(item->childItem(i), type, id); if (foundItem) { return foundItem; } } if (m_doc->loading()) { DEBUG(DBG_SRC) << "could not find " << v->umlScene()->name() << " in " << *item; } else { uWarning() << "could not find " << v->umlScene()->name() << " in " << *item; } return 0; } /** * Searches the tree for a diagram (view). * Warning: these method may return in some cases the wrong diagram * Used by findView(). */ UMLListViewItem* UMLListView::recursiveSearchForView(UMLListViewItem* listViewItem, UMLListViewItem::ListViewType type, Uml::ID::Type id) { if (!listViewItem) return 0; if (Model_Utils::typeIsFolder(listViewItem->type())) { for (int i=0; i < listViewItem->childCount(); i++) { UMLListViewItem* child = listViewItem->childItem(i); UMLListViewItem* resultListViewItem = recursiveSearchForView(child, type, id); if (resultListViewItem) return resultListViewItem; } } else { if (listViewItem->type() == type && listViewItem->ID() == id) return listViewItem; } return 0; } /** * Searches through the tree for the item with the given ID. * * @param id The ID to search for. * @return The item with the given ID or 0 if not found. */ UMLListViewItem* UMLListView::findItem(Uml::ID::Type id) { UMLListViewItem *topLevel = m_rv; UMLListViewItem *item = topLevel->findItem(id); if (item) return item; return 0; } /** * Carries out initalisation of attributes in class. * This method is called more than once during an instance's lifetime (by UMLDoc)! * So we must not allocate any memory before freeing the previously allocated one * or do connect()s. */ void UMLListView::init() { if (m_rv == 0) { m_rv = new UMLListViewItem(this, i18n("Views"), UMLListViewItem::lvt_View); m_rv->setID("Views"); //m_rv->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator); for (int i = 0; i < Uml::ModelType::N_MODELTYPES; ++i) { Uml::ModelType::Enum mt = Uml::ModelType::fromInt(i); UMLFolder *sysFolder = m_doc->rootFolder(mt); UMLListViewItem::ListViewType lvt = Model_Utils::convert_MT_LVT(mt); m_lv[i] = new UMLListViewItem(m_rv, sysFolder->localName(), lvt, sysFolder); } } else { clean(); } UMLFolder *datatypeFolder = m_doc->datatypeFolder(); if (!m_datatypeFolder) { m_datatypeFolder = new UMLListViewItem(m_lv[Uml::ModelType::Logical], datatypeFolder->localName(), UMLListViewItem::lvt_Datatype_Folder, datatypeFolder); } if (m_settingsFolder == 0) { m_settingsFolder = new UMLListViewItem(this, i18n("Settings"), UMLListViewItem::lvt_Properties); Icon_Utils::IconType icon = Model_Utils::convert_LVT_IT(m_settingsFolder->type()); m_settingsFolder->setIcon(icon); m_settingsFolder->setID("Settings"); new UMLListViewItem(m_settingsFolder, i18n("Auto Layout"), UMLListViewItem::lvt_Properties_AutoLayout); new UMLListViewItem(m_settingsFolder, i18n("Class"), UMLListViewItem::lvt_Properties_Class); new UMLListViewItem(m_settingsFolder, i18n("Code Importer"), UMLListViewItem::lvt_Properties_CodeImport); new UMLListViewItem(m_settingsFolder, i18n("Code Generation"), UMLListViewItem::lvt_Properties_CodeGeneration); new UMLListViewItem(m_settingsFolder, i18n("Code Viewer"), UMLListViewItem::lvt_Properties_CodeViewer); new UMLListViewItem(m_settingsFolder, i18n("Font"), UMLListViewItem::lvt_Properties_Font); new UMLListViewItem(m_settingsFolder, i18n("General"), UMLListViewItem::lvt_Properties_General); new UMLListViewItem(m_settingsFolder, i18n("User Interface"), UMLListViewItem::lvt_Properties_UserInterface); } m_rv->setOpen(true); for (int i = 0; i < Uml::ModelType::N_MODELTYPES; ++i) { m_lv[i]->setOpen(true); } m_datatypeFolder->setOpen(false); //setup misc. m_bStartedCut = m_bStartedCopy = false; m_bCreatingChildObject = false; headerItem()->setHidden(true); } /** * Remove all items and subfolders of the main folders. * Special case: The datatype folder, child of the logical view, is not deleted. */ void UMLListView::clean() { for (int i = 0; i < Uml::ModelType::N_MODELTYPES; ++i) { deleteChildrenOf(m_lv[i]); } //deleteChildrenOf(m_datatypeFolder); } /** * Set the current view to the given view. * * @param view The current view. */ void UMLListView::setView(UMLView * view) { if (!view) return; UMLListViewItem * temp = findView(view); if (temp) temp->setSelected(true); } /** * Event handler for mouse double click. */ void UMLListView::mouseDoubleClickEvent(QMouseEvent * me) { UMLListViewItem * item = static_cast(currentItem()); if (!item || me->button() != Qt::LeftButton) return; UMLListViewItem::ListViewType lvType = item->type(); if (Model_Utils::typeIsProperties(lvType)) { UMLApp::app()->docWindow()->updateDocumentation(false); UMLApp::app()->slotPrefs(Model_Utils::convert_LVT_PT(lvType)); return; } else if (Model_Utils::typeIsDiagram(lvType)) { UMLView * pView = m_doc->findView(item->ID()); if (pView) { UMLApp::app()->docWindow()->updateDocumentation(false); pView->showPropertiesDialog(); UMLApp::app()->docWindow()->showDocumentation(pView->umlScene(), true); } return; } //else see if an object UMLObject * object = item->umlObject(); //continue only if we are on a UMLObject if (!object) { return; } object->showPropertiesDialog(this); } /** * Event handler for accepting drag request. * @param event the drop event * @return success state */ bool UMLListView::acceptDrag(QDropEvent* event) const { UMLListViewItem* target = (UMLListViewItem*)itemAt(event->pos()); if (!target) { DEBUG(DBG_SRC) << "itemAt(mouse position) returns 0"; return false; } bool accept = false; UMLListViewItem::ListViewType srcType = UMLListViewItem::lvt_Unknown; UMLListViewItem::ListViewType dstType = UMLListViewItem::lvt_Unknown; // Handle different drop actions switch (event->proposedAction()) { case Qt::CopyAction: { // Instead of relying on the current item being the drag source, // we should use the mime data to obtain the dragged type (or types // if we implement multiple item selections in tree view) srcType = static_cast(currentItem())->type(); dstType = target->type(); // Copy of diagrams is not supported if (Model_Utils::typeIsDiagram(srcType)) { accept = false; } else { accept = Model_Utils::typeIsAllowedInType(srcType, dstType); } break; } case Qt::MoveAction: { UMLDragData::LvTypeAndID_List list; if (!UMLDragData::getClip3TypeAndID(event->mimeData(), list)) { uError() << "UMLDragData::getClip3TypeAndID returns false"; return false; } UMLDragData::LvTypeAndID_It it(list); UMLDragData::LvTypeAndID * data = 0; dstType = target->type(); while (it.hasNext()) { data = it.next(); srcType = data->type; accept = Model_Utils::typeIsAllowedInType(srcType, dstType); // disallow drop if any child element is not allowed if (!accept) break; } break; } default: { uError() << "Unsupported drop-action in acceptDrag()"; return false; } } if (!accept) { uDebug() << "Disallowing drop because source type" << UMLListViewItem::toString(srcType) << "is not allowed in target type" << UMLListViewItem::toString(dstType); } return accept; } /** * Auxiliary method for moveObject(): Adds the model object at the proper * new container (package if nested, UMLDoc if at global level), and * updates the containment relationships in the model. */ void UMLListView::addAtContainer(UMLListViewItem *item, UMLListViewItem *parent) { UMLCanvasObject *o = item->umlObject()->asUMLCanvasObject(); if (o == 0) { DEBUG(DBG_SRC) << item->text(0) << ": item's UMLObject is 0"; } else if (Model_Utils::typeIsContainer(parent->type())) { /**** TBC: Do this here? If yes then remove that logic at the callers and rename this method to moveAtContainer() UMLPackage *oldPkg = o->getUMLPackage(); if (oldPkg) oldPkg->removeObject(o); *********/ UMLPackage *pkg = parent->umlObject()->asUMLPackage(); o->setUMLPackage(pkg); pkg->addObject(o); } else { uError() << item->text(0) << ": parent type is " << parent->type(); } UMLView *currentView = UMLApp::app()->currentView(); if (currentView) currentView->umlScene()->updateContainment(o); } /** * Moves an object given is unique ID and listview type to an * other listview parent item. * Also takes care of the corresponding move in the model. */ UMLListViewItem * UMLListView::moveObject(Uml::ID::Type srcId, UMLListViewItem::ListViewType srcType, UMLListViewItem *newParent) { if (newParent == 0) return 0; UMLListViewItem * move = findItem(srcId); if (move == 0) return 0; UMLObject *newParentObj = 0; // Remove the source object at the old parent package. UMLObject *srcObj = m_doc->findObjectById(srcId); if (srcObj) { newParentObj = newParent->umlObject(); if (srcObj == newParentObj) { uError() << srcObj->name() << ": Cannot move onto self"; return 0; } UMLPackage *srcPkg = srcObj->umlPackage(); if (srcPkg) { if (srcPkg == newParentObj) { uError() << srcObj->name() << ": Object is already in target package"; return 0; } srcPkg->removeObject(srcObj); } } else if (Model_Utils::typeIsDiagram(srcType)) { UMLView *v = m_doc->findView(srcId); UMLFolder *newParentObj = newParent->umlObject()->asUMLFolder(); if (v) { UMLFolder *srcPkg = v->umlScene()->folder(); if (srcPkg) { if (srcPkg == newParentObj) { uError() << v->umlScene()->name() << ": Object is already in target package"; return 0; } srcPkg->removeView(v); newParentObj->addView(v); v->umlScene()->setFolder(newParentObj); UMLApp::app()->document()->diagramsModel()->emitDataChanged(v); } } } UMLListViewItem::ListViewType newParentType = newParent->type(); DEBUG(DBG_SRC) << "newParentType is " << UMLListViewItem::toString(newParentType); UMLListViewItem *newItem = 0; //make sure trying to place in correct location switch (srcType) { case UMLListViewItem::lvt_UseCase_Folder: case UMLListViewItem::lvt_Actor: case UMLListViewItem::lvt_UseCase: case UMLListViewItem::lvt_UseCase_Diagram: if (newParentType == UMLListViewItem::lvt_UseCase_Folder || newParentType == UMLListViewItem::lvt_UseCase_View) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_Component_Folder: case UMLListViewItem::lvt_Artifact: case UMLListViewItem::lvt_Component_Diagram: if (newParentType == UMLListViewItem::lvt_Component_Folder || newParentType == UMLListViewItem::lvt_Component_View) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_Subsystem: if (newParentType == UMLListViewItem::lvt_Component_Folder || newParentType == UMLListViewItem::lvt_Component_View || newParentType == UMLListViewItem::lvt_Subsystem) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_Component: if (newParentType == UMLListViewItem::lvt_Component_Folder || newParentType == UMLListViewItem::lvt_Component_View || newParentType == UMLListViewItem::lvt_Component || newParentType == UMLListViewItem::lvt_Subsystem) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_Port: if (newParentType == UMLListViewItem::lvt_Component) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_Deployment_Folder: case UMLListViewItem::lvt_Node: case UMLListViewItem::lvt_Deployment_Diagram: if (newParentType == UMLListViewItem::lvt_Deployment_Folder || newParentType == UMLListViewItem::lvt_Deployment_View) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_EntityRelationship_Folder: case UMLListViewItem::lvt_Entity: case UMLListViewItem::lvt_Category: case UMLListViewItem::lvt_EntityRelationship_Diagram: if (newParentType == UMLListViewItem::lvt_EntityRelationship_Folder || newParentType == UMLListViewItem::lvt_EntityRelationship_Model) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_Collaboration_Diagram: case UMLListViewItem::lvt_Class_Diagram: case UMLListViewItem::lvt_State_Diagram: case UMLListViewItem::lvt_Activity_Diagram: case UMLListViewItem::lvt_Sequence_Diagram: case UMLListViewItem::lvt_Logical_Folder: case UMLListViewItem::lvt_Object_Diagram: if (newParentType == UMLListViewItem::lvt_Logical_Folder || newParentType == UMLListViewItem::lvt_Logical_View) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; addAtContainer(newItem, newParent); } break; case UMLListViewItem::lvt_Class: case UMLListViewItem::lvt_Package: case UMLListViewItem::lvt_Interface: case UMLListViewItem::lvt_Enum: case UMLListViewItem::lvt_Datatype: if (newParentType == UMLListViewItem::lvt_Logical_Folder || newParentType == UMLListViewItem::lvt_Datatype_Folder || newParentType == UMLListViewItem::lvt_Logical_View || newParentType == UMLListViewItem::lvt_Class || newParentType == UMLListViewItem::lvt_Interface || newParentType == UMLListViewItem::lvt_Package) { newItem = move->deepCopy(newParent); if (m_doc->loading()) // deletion is not safe while loading move->setVisible(false); // (the XMI may be corrupted) else delete move; UMLCanvasObject *o = newItem->umlObject()->asUMLCanvasObject(); if (o == 0) { DEBUG(DBG_SRC) << "moveObject: newItem's UMLObject is 0"; } else if (newParentObj == 0) { uError() << o->name() << ": newParentObj is 0"; } else { UMLPackage *pkg = newParentObj->asUMLPackage(); o->setUMLPackage(pkg); pkg->addObject(o); } UMLView *currentView = UMLApp::app()->currentView(); if (currentView) currentView->umlScene()->updateContainment(o); } break; case UMLListViewItem::lvt_Attribute: case UMLListViewItem::lvt_Operation: if (newParentType == UMLListViewItem::lvt_Class || newParentType == UMLListViewItem::lvt_Interface) { // update list view newItem = move->deepCopy(newParent); // we don't delete move right away, it will be deleted in slots, // called by subsequent steps //delete move; // update model objects m_bCreatingChildObject = true; if (!srcObj) { uError() << "srcObj is NULL"; break; } UMLClassifier *oldParentClassifier = srcObj->umlParent()->asUMLClassifier(); UMLClassifier *newParentClassifier = newParentObj->asUMLClassifier(); if (srcType == UMLListViewItem::lvt_Attribute) { UMLAttribute *att = srcObj->asUMLAttribute(); // We can't use the existing 'att' directly // because its parent is fixed to the old classifier // and we have no way of changing that: // QObject does not permit changing the parent(). if (att == 0) { uError() << "moveObject internal error: srcObj " << srcObj->name() << " is not a UMLAttribute"; } else if (oldParentClassifier->takeItem(att) == -1) { uError() << "moveObject: oldParentClassifier->takeItem(att " << att->name() << ") returns 0"; } else { const QString& nm = att->name(); UMLAttribute *newAtt = newParentClassifier->createAttribute(nm, att->getType(), att->visibility(), att->getInitialValue()); newItem->setUMLObject(newAtt); newParent->addClassifierListItem(newAtt, newItem); connectNewObjectsSlots(newAtt); // Let's not forget to update the DocWindow::m_pObject // because the old one is about to be physically deleted ! UMLApp::app()->docWindow()->showDocumentation(newAtt, true); delete att; } } else { UMLOperation *op = srcObj->asUMLOperation(); // We can't use the existing 'op' directly // because its parent is fixed to the old classifier // and we have no way of changing that: // QObject does not permit changing the parent(). if (op && oldParentClassifier->takeItem(op) != -1) { bool isExistingOp; Model_Utils::NameAndType_List ntDummyList; // We need to provide a dummy NameAndType_List // else UMLClassifier::createOperation will // bring up an operation dialog. UMLOperation *newOp = newParentClassifier->createOperation( op->name(), &isExistingOp, &ntDummyList); newOp->setType(op->getType()); newOp->setVisibility(op->visibility()); UMLAttributeList parmList = op->getParmList(); foreach(UMLAttribute* parm, parmList) { UMLAttribute *newParm = new UMLAttribute(newParentClassifier, parm->name(), Uml::ID::None, parm->visibility(), parm->getType(), parm->getInitialValue()); newParm->setParmKind(parm->getParmKind()); newOp->addParm(newParm); } newItem->setUMLObject(newOp); newParent->addClassifierListItem(newOp, newItem); connectNewObjectsSlots(newOp); // Let's not forget to update the DocWindow::m_pObject // because the old one is about to be physically deleted ! UMLApp::app()->docWindow()->showDocumentation(newOp, true); delete op; } else { uError() << "moveObject: oldParentClassifier->takeItem(op) returns 0"; } } m_bCreatingChildObject = false; } break; default: break; } return newItem; } /** * Something has been dragged and dropped onto the list view. */ void UMLListView::slotDropped(QDropEvent* de, UMLListViewItem* target) { DEBUG(DBG_SRC) << "Dropping on target " << target->text(0); // Copy or move tree items if (de->dropAction() == Qt::CopyAction) { UMLClipboard clipboard; // Todo: refactor UMLClipboard to support pasting to a non-current item setCurrentItem(target); // Paste the data (not always clip3) if (!clipboard.paste(m_dragCopyData)) { uError() << "Unable to copy selected item into the target item"; } } else { UMLDragData::LvTypeAndID_List srcList; if (! UMLDragData::getClip3TypeAndID(de->mimeData(), srcList)) { uError() << "Unexpected mime data in drop event"; return; } UMLDragData::LvTypeAndID_It it(srcList); UMLDragData::LvTypeAndID * src = 0; while (it.hasNext()) { src = it.next(); moveObject(src->id, src->type, target); } } } /** * Get selected items. * @return the list of selected items */ UMLListViewItemList UMLListView::selectedItems() { UMLListViewItemList itemList; UMLListViewItemIterator it(this); // iterate through all items of the list view for (; *it; ++it) { if ((*it)->isSelected()) { UMLListViewItem *item = (UMLListViewItem*)*it; itemList.append(item); } } // DEBUG(DBG_SRC) << "selected items = " << itemList.count(); return itemList; } /** * Get selected items, but only root elements selected (without children). * @return the list of selected root items */ UMLListViewItemList UMLListView::selectedItemsRoot() { UMLListViewItemList itemList; QTreeWidgetItemIterator it(this); // iterate through all items of the list view for (; *it; ++it) { if ((*it)->isSelected()) { UMLListViewItem *item = (UMLListViewItem*)*it; // this is the trick, we select only the item with a parent unselected // since we can't select a child and its grandfather without its parent // we would be able to delete each item individually, without an invalid iterator if (item && item->parent() && item->parent()->isSelected() == false) { itemList.append(item); } } } return itemList; } /** * Create a listview item for an existing diagram. * * @param view The existing diagram. */ UMLListViewItem* UMLListView::createDiagramItem(UMLView *view) { if (!view) { return 0; } UMLListViewItem::ListViewType lvt = Model_Utils::convert_DT_LVT(view->umlScene()->type()); UMLListViewItem *parent = 0; UMLFolder *f = view->umlScene()->folder(); if (f) { parent = findUMLObject(f); if (parent == 0) uError() << view->umlScene()->name() << ": findUMLObject(" << f->name() << ") returns 0"; } else { DEBUG(DBG_SRC) << view->umlScene()->name() << ": no parent folder set, using predefined folder"; } if (parent == 0) { parent = determineParentItem(lvt); lvt = Model_Utils::convert_DT_LVT(view->umlScene()->type()); } UMLListViewItem *item = new UMLListViewItem(parent, view->umlScene()->name(), lvt, view->umlScene()->ID()); return item; } /** * Determine the parent ListViewItem given a ListViewType. * This parent is used for creating new UMLListViewItems. * * @param lvt The ListViewType for which to lookup the parent. * @return Pointer to the parent UMLListViewItem chosen. */ UMLListViewItem* UMLListView::determineParentItem(UMLListViewItem::ListViewType lvt) const { UMLListViewItem* parent = 0; switch (lvt) { case UMLListViewItem::lvt_Datatype: parent = m_datatypeFolder; break; case UMLListViewItem::lvt_Actor: case UMLListViewItem::lvt_UseCase: case UMLListViewItem::lvt_UseCase_Folder: case UMLListViewItem::lvt_UseCase_Diagram: parent = m_lv[Uml::ModelType::UseCase]; break; case UMLListViewItem::lvt_Component_Diagram: case UMLListViewItem::lvt_Component: case UMLListViewItem::lvt_Port: case UMLListViewItem::lvt_Artifact: parent = m_lv[Uml::ModelType::Component]; break; case UMLListViewItem::lvt_Deployment_Diagram: case UMLListViewItem::lvt_Node: parent = m_lv[Uml::ModelType::Deployment]; break; case UMLListViewItem::lvt_EntityRelationship_Diagram: case UMLListViewItem::lvt_Entity: case UMLListViewItem::lvt_Category: parent = m_lv[Uml::ModelType::EntityRelationship]; break; default: if (Model_Utils::typeIsDiagram(lvt) || !Model_Utils::typeIsClassifierList(lvt)) parent = m_lv[Uml::ModelType::Logical]; break; } return parent; } /** * Return the amount of items selected. */ int UMLListView::selectedItemsCount() { UMLListViewItemList items = selectedItems(); return items.count(); } /** * Returns the document pointer. Called by the UMLListViewItem class. */ UMLDoc * UMLListView::document() const { return m_doc; } /** * Event handler for lost focus. * @param fe the focus event */ void UMLListView::focusOutEvent(QFocusEvent * fe) { Qt::FocusReason reason = fe->reason(); if (reason != Qt::PopupFocusReason && reason != Qt::MouseFocusReason) { clearSelection(); //triggerUpdate(); } //repaint(); QTreeWidget::focusOutEvent(fe); } void UMLListView::contextMenuEvent(QContextMenuEvent *event) { // Get the UMLListViewItem at the point where the mouse pointer was pressed UMLListViewItem * item = static_cast(itemAt(event->pos())); if (item) { UMLListViewPopupMenu popup(this, item); QAction *triggered = popup.exec(event->globalPos()); slotMenuSelection(triggered, event->globalPos()); event->accept(); } QTreeWidget::contextMenuEvent(event); } /** * Determines the root listview type of the given UMLListViewItem. * Starts at the given item, compares it against each of the * predefined root views (Root, Logical, UseCase, Component, * Deployment, EntityRelationship.) Returns the ListViewType * of the matching root view; if no match then continues the * search using the item's parent, then grandparent, and so forth. * Returns UMLListViewItem::lvt_Unknown if no match at all is found. */ UMLListViewItem::ListViewType UMLListView::rootViewType(UMLListViewItem *item) { if (item == m_rv) return UMLListViewItem::lvt_View; if (item == m_lv[Uml::ModelType::Logical]) return UMLListViewItem::lvt_Logical_View; if (item == m_lv[Uml::ModelType::UseCase]) return UMLListViewItem::lvt_UseCase_View; if (item == m_lv[Uml::ModelType::Component]) return UMLListViewItem::lvt_Component_View; if (item == m_lv[Uml::ModelType::Deployment]) return UMLListViewItem::lvt_Deployment_View; if (item == m_lv[Uml::ModelType::EntityRelationship]) return UMLListViewItem::lvt_EntityRelationship_Model; UMLListViewItem *parent = dynamic_cast(item->parent()); if (parent) return rootViewType(parent); return UMLListViewItem::lvt_Unknown; } /** * Return true if the given list view type can be expanded/collapsed. */ bool UMLListView::isExpandable(UMLListViewItem::ListViewType lvt) { if (Model_Utils::typeIsRootView(lvt) || Model_Utils::typeIsFolder(lvt)) return true; switch (lvt) { case UMLListViewItem::lvt_Package: case UMLListViewItem::lvt_Component: case UMLListViewItem::lvt_Subsystem: return true; break; default: break; } return false; } /** * Calls updateFolder() on the item to update the icon to open. */ void UMLListView::slotExpanded(QTreeWidgetItem * item) { UMLListViewItem * myItem = dynamic_cast(item); if (!myItem) return; if (isExpandable(myItem->type())) { myItem->updateFolder(); } } /** * Calls updateFolder() on the item to update the icon to closed. */ void UMLListView::slotCollapsed(QTreeWidgetItem * item) { UMLListViewItem * myItem = dynamic_cast(item); if (!myItem) return; if (isExpandable(myItem->type())) { myItem->updateFolder(); } } /** * Connects to the signal that @ref UMLApp emits when a * cut operation is successful. */ void UMLListView::slotCutSuccessful() { if (m_bStartedCut) { UMLListViewItem* item = static_cast(currentItem()); deleteItem(item); m_bStartedCut = false; } } /** * Delete every selected item */ void UMLListView::slotDeleteSelectedItems() { UMLListViewItemList itemsSelected = selectedItemsRoot(); foreach(UMLListViewItem *item, itemsSelected) { deleteItem(item); } } /** * Adds a new item to the tree of the given type under the given parent. * Method will take care of signalling anyone needed on creation of new item. * e.g. UMLDoc if an UMLObject is created. */ void UMLListView::addNewItem(UMLListViewItem *parentItem, UMLListViewItem::ListViewType type) { if (type == UMLListViewItem::lvt_Datatype) { parentItem = m_datatypeFolder; } parentItem->setOpen(true); // Determine the UMLObject belonging to the listview item we're using as parent UMLObject* parent = parentItem->umlObject(); if (parent == 0) { uError() << "UMLListView::addNewItem - " << UMLListViewItem::toString(type) << ": parentPkg is 0"; return; } if (Model_Utils::typeIsDiagram(type)) { Uml::DiagramType::Enum diagramType = Model_Utils::convert_LVT_DT(type); QString diagramName = m_doc->createDiagramName(diagramType); if (diagramName.isEmpty()) { // creation was cancelled by the user return; } UMLFolder* parent = parentItem->umlObject()->asUMLFolder(); UMLApp::app()->executeCommand(new Uml::CmdCreateDiagram(m_doc, diagramType, diagramName, parent)); return; } // Determine the ObjectType of the new object UMLObject::ObjectType objectType = Model_Utils::convert_LVT_OT(type); if (objectType == UMLObject::ot_UMLObject) { uError() << "no UMLObject for type " << UMLListViewItem::toString(type); return; } if (Model_Utils::typeIsClassifierList(type)) { UMLClassifier* classifier = parent->asUMLClassifier(); QString name = classifier->uniqChildName(objectType); UMLObject* object = Object_Factory::createChildObject(classifier, objectType, name); if (object == 0) { // creation was cancelled by the user return; } // Handle primary key constraints (mark the unique constraint as PK on // the parent entity) if (type == UMLListViewItem::lvt_PrimaryKeyConstraint) { UMLUniqueConstraint* uuc = object->asUMLUniqueConstraint(); UMLEntity* ent = uuc ? uuc->umlParent()->asUMLEntity() : 0; if (ent) { ent->setAsPrimaryKey(uuc); } } } else { UMLPackage* package = parent->asUMLPackage(); QString name = Model_Utils::uniqObjectName(objectType, package); UMLObject* object = Object_Factory::createUMLObject(objectType, name, package); if (object == 0) { // creation was cancelled by the user return; } if (type == UMLListViewItem::lvt_Subsystem) { object->setStereotypeCmd(QLatin1String("subsystem")); } else if (Model_Utils::typeIsFolder(type)) { object->setStereotypeCmd(QLatin1String("folder")); } } } /** * Returns if the given name is unique for the given items type. */ bool UMLListView::isUnique(UMLListViewItem * item, const QString &name) { UMLListViewItem * parentItem = static_cast(item->parent()); UMLListViewItem::ListViewType type = item->type(); switch (type) { case UMLListViewItem::lvt_Class_Diagram: return !m_doc->findView(Uml::DiagramType::Class, name); break; case UMLListViewItem::lvt_Sequence_Diagram: return !m_doc->findView(Uml::DiagramType::Sequence, name); break; case UMLListViewItem::lvt_UseCase_Diagram: return !m_doc->findView(Uml::DiagramType::UseCase, name); break; case UMLListViewItem::lvt_Collaboration_Diagram: return !m_doc->findView(Uml::DiagramType::Collaboration, name); break; case UMLListViewItem::lvt_State_Diagram: return !m_doc->findView(Uml::DiagramType::State, name); break; case UMLListViewItem::lvt_Activity_Diagram: return !m_doc->findView(Uml::DiagramType::Activity, name); break; case UMLListViewItem::lvt_Component_Diagram: return !m_doc->findView(Uml::DiagramType::Component, name); break; case UMLListViewItem::lvt_Deployment_Diagram: return !m_doc->findView(Uml::DiagramType::Deployment, name); break; case UMLListViewItem::lvt_EntityRelationship_Diagram: return !m_doc->findView(Uml::DiagramType::EntityRelationship, name); break; case UMLListViewItem::lvt_Object_Diagram: return !m_doc->findView(Uml::DiagramType::Object, name); break; case UMLListViewItem::lvt_Actor: case UMLListViewItem::lvt_UseCase: case UMLListViewItem::lvt_Node: case UMLListViewItem::lvt_Artifact: case UMLListViewItem::lvt_Category: return !m_doc->findUMLObject(name, Model_Utils::convert_LVT_OT(type)); break; case UMLListViewItem::lvt_Class: case UMLListViewItem::lvt_Package: case UMLListViewItem::lvt_Interface: case UMLListViewItem::lvt_Datatype: case UMLListViewItem::lvt_Enum: case UMLListViewItem::lvt_Entity: case UMLListViewItem::lvt_Component: case UMLListViewItem::lvt_Port: case UMLListViewItem::lvt_Subsystem: case UMLListViewItem::lvt_Logical_Folder: case UMLListViewItem::lvt_UseCase_Folder: case UMLListViewItem::lvt_Component_Folder: case UMLListViewItem::lvt_Deployment_Folder: case UMLListViewItem::lvt_EntityRelationship_Folder: { UMLListViewItem::ListViewType lvt = parentItem->type(); if (!Model_Utils::typeIsContainer(lvt)) return (m_doc->findUMLObject(name) == 0); UMLPackage *pkg = parentItem->umlObject()->asUMLPackage(); if (pkg == 0) { uError() << "internal error - " << "parent listviewitem is package but has no UMLObject"; return true; } return (pkg->findObject(name) == 0); break; } case UMLListViewItem::lvt_Template: case UMLListViewItem::lvt_Attribute: case UMLListViewItem::lvt_EntityAttribute: case UMLListViewItem::lvt_InstanteAttribute: case UMLListViewItem::lvt_Operation: case UMLListViewItem::lvt_EnumLiteral: case UMLListViewItem::lvt_UniqueConstraint: case UMLListViewItem::lvt_PrimaryKeyConstraint: case UMLListViewItem::lvt_ForeignKeyConstraint: case UMLListViewItem::lvt_CheckConstraint: { UMLClassifier *parent = parentItem->umlObject()->asUMLClassifier(); if (parent == 0) { uError() << "internal error - " << "parent listviewitem is package but has no UMLObject"; return true; } return (parent->findChildObject(name) == 0); break; } default: break; } return false; } /** * */ void UMLListView::saveToXMI1(QDomDocument & qDoc, QDomElement & qElement) { QDomElement listElement = qDoc.createElement(QLatin1String("listview")); m_rv->saveToXMI1(qDoc, listElement); qElement.appendChild(listElement); } /** * */ bool UMLListView::loadFromXMI1(QDomElement & element) { QDomNode node = element.firstChild(); QDomElement domElement = node.toElement(); m_doc->writeToStatusBar(i18n("Loading listview...")); while (!domElement.isNull()) { if (domElement.tagName() == QLatin1String("listitem")) { QString type = domElement.attribute(QLatin1String("type"), QLatin1String("-1")); if (type == QLatin1String("-1")) return false; UMLListViewItem::ListViewType lvType = (UMLListViewItem::ListViewType)type.toInt(); if (lvType == UMLListViewItem::lvt_View) { if (!loadChildrenFromXMI(m_rv, domElement)) return false; } else return false; } node = node.nextSibling(); domElement = node.toElement(); }//end while return true; } /** * */ bool UMLListView::loadChildrenFromXMI(UMLListViewItem * parent, QDomElement & element) { QDomNode node = element.firstChild(); QDomElement domElement = node.toElement(); while (!domElement.isNull()) { node = domElement.nextSibling(); if (domElement.tagName() != QLatin1String("listitem")) { domElement = node.toElement(); continue; } QString id = domElement.attribute(QLatin1String("id"), QLatin1String("-1")); QString type = domElement.attribute(QLatin1String("type"), QLatin1String("-1")); QString label = domElement.attribute(QLatin1String("label")); QString open = domElement.attribute(QLatin1String("open"), QLatin1String("1")); if (type == QLatin1String("-1")) return false; UMLListViewItem::ListViewType lvType = (UMLListViewItem::ListViewType)type.toInt(); bool bOpen = (bool)open.toInt(); Uml::ID::Type nID = Uml::ID::fromString(id); UMLObject * pObject = 0; UMLListViewItem * item = 0; if (nID != Uml::ID::None) { // The following is an ad hoc hack for the copy/paste code. // The clip still contains the old children although new // UMLCLassifierListItems have already been created. // If the IDChangeLog finds new IDs this means we are in // copy/paste and need to adjust the child listitems to the // new UMLCLassifierListItems. IDChangeLog *idchanges = m_doc->changeLog(); if (idchanges) { Uml::ID::Type newID = idchanges->findNewID(nID); if (newID != Uml::ID::None) { DEBUG(DBG_SRC) << " using id " << Uml::ID::toString(newID) << " instead of " << Uml::ID::toString(nID); nID = newID; } } /************ End of hack for copy/paste code ************/ pObject = m_doc->findObjectById(nID); if (pObject) { if (label.isEmpty()) label = pObject->name(); } else if (Model_Utils::typeIsFolder(lvType)) { // Synthesize the UMLFolder here UMLObject *umlParent = parent->umlObject(); UMLPackage *parentPkg = umlParent->asUMLPackage(); if (parentPkg == 0) { uError() << "umlParent(" << umlParent << ") is not a UMLPackage"; domElement = node.toElement(); continue; } UMLFolder *f = new UMLFolder(label, nID); f->setUMLPackage(parentPkg); parentPkg->addObject(f); pObject = f; item = new UMLListViewItem(parent, label, lvType, pObject); // Moving all relevant UMLObjects to the new UMLFolder is done below, // in the switch(lvType) } } else if (Model_Utils::typeIsRootView(lvType)) { // Predefined folders did not have their ID set. const Uml::ModelType::Enum mt = Model_Utils::convert_LVT_MT(lvType); nID = m_doc->rootFolder(mt)->id(); } else if (Model_Utils::typeIsFolder(lvType)) { // Pre-1.2 format: Folders did not have their ID set. // Pull a new ID now. nID = m_doc->rootFolder(Uml::ModelType::Logical)->id(); } else { uError() << "item of type " << type << " has no ID, skipping."; domElement = node.toElement(); continue; } switch (lvType) { case UMLListViewItem::lvt_Actor: case UMLListViewItem::lvt_UseCase: case UMLListViewItem::lvt_Class: case UMLListViewItem::lvt_Instance: case UMLListViewItem::lvt_Interface: case UMLListViewItem::lvt_Datatype: case UMLListViewItem::lvt_Enum: case UMLListViewItem::lvt_Entity: case UMLListViewItem::lvt_Package: case UMLListViewItem::lvt_Subsystem: case UMLListViewItem::lvt_Component: case UMLListViewItem::lvt_Port: case UMLListViewItem::lvt_Node: case UMLListViewItem::lvt_Artifact: case UMLListViewItem::lvt_Logical_Folder: case UMLListViewItem::lvt_UseCase_Folder: case UMLListViewItem::lvt_Component_Folder: case UMLListViewItem::lvt_Deployment_Folder: case UMLListViewItem::lvt_EntityRelationship_Folder: case UMLListViewItem::lvt_Category: item = findItem(nID); if (item == 0) { uError() << "INTERNAL ERROR: " << "findItem(id " << Uml::ID::toString(nID) << ") returns 0"; } else if (parent != item->parent()) { // The existing item was created by the slot event triggered // by the loading of the corresponding model object from the // XMI file. UMLListViewItem *itmParent = dynamic_cast(item->parent()); DEBUG(DBG_SRC) << "Loaded entry does not match uml model" << item->text(0) << " parent " << parent->text(0) << " (" << parent << ") != " << (itmParent ? itmParent->text(0) : QLatin1String("")) << " (" << itmParent << ")"; } break; case UMLListViewItem::lvt_Attribute: case UMLListViewItem::lvt_EntityAttribute: case UMLListViewItem::lvt_InstanteAttribute: case UMLListViewItem::lvt_Template: case UMLListViewItem::lvt_Operation: case UMLListViewItem::lvt_EnumLiteral: case UMLListViewItem::lvt_UniqueConstraint: case UMLListViewItem::lvt_PrimaryKeyConstraint: case UMLListViewItem::lvt_ForeignKeyConstraint: case UMLListViewItem::lvt_CheckConstraint: item = findItem(nID); if (item == 0) { DEBUG(DBG_SRC) << "item " << Uml::ID::toString(nID) << " (of type " << UMLListViewItem::toString(lvType) << ") does not yet exist..."; UMLObject* umlObject = parent->umlObject(); if (!umlObject) { DEBUG(DBG_SRC) << "And also the parent->umlObject() does not exist"; return false; } if (nID == Uml::ID::None) { uWarning() << "lvtype " << UMLListViewItem::toString(lvType) << " has id -1"; } else { UMLClassifier *classifier = umlObject->asUMLClassifier(); if (classifier) { umlObject = classifier->findChildObjectById(nID); if (umlObject) { connectNewObjectsSlots(umlObject); label = umlObject->name(); item = new UMLListViewItem(parent, label, lvType, umlObject); } else { DEBUG(DBG_SRC) << "lvtype " << UMLListViewItem::toString(lvType) << " child object " << Uml::ID::toString(nID) << " not found"; } } else { DEBUG(DBG_SRC) << "cast to classifier object failed"; } } } break; case UMLListViewItem::lvt_Logical_View: item = m_lv[Uml::ModelType::Logical]; break; case UMLListViewItem::lvt_Datatype_Folder: item = m_datatypeFolder; break; case UMLListViewItem::lvt_UseCase_View: item = m_lv[Uml::ModelType::UseCase]; break; case UMLListViewItem::lvt_Component_View: item = m_lv[Uml::ModelType::Component]; break; case UMLListViewItem::lvt_Deployment_View: item = m_lv[Uml::ModelType::Deployment]; break; case UMLListViewItem::lvt_EntityRelationship_Model: item = m_lv[Uml::ModelType::EntityRelationship]; break; default: if (Model_Utils::typeIsDiagram(lvType)) { item = new UMLListViewItem(parent, label, lvType, nID); } else { uError() << "INTERNAL ERROR: unexpected listview type " << UMLListViewItem::toString(lvType) << " (ID " << Uml::ID::toString(nID) << ")"; } break; }//end switch if (item) { item->setOpen((bool)bOpen); if (!loadChildrenFromXMI(item, domElement)) { return false; } } else { uWarning() << "unused list view item " << Uml::ID::toString(nID) << " of lvtype " << UMLListViewItem::toString(lvType); } domElement = node.toElement(); }//end while return true; } /** * Open all items in the list view. */ void UMLListView::expandAll(UMLListViewItem *item) { if (!item) item = m_rv; for (int i = 0; i < item->childCount(); i++) { expandAll(item->childItem(i)); } item->setExpanded(true); } /** * Close all items in the list view. */ void UMLListView::collapseAll(UMLListViewItem *item) { if (!item) item = m_rv; for (int i = 0; i < item->childCount(); i++) { collapseAll(item->childItem(i)); } item->setExpanded(false); } /** * Set the variable m_bStartedCut * to indicate that selection should be deleted * in slotCutSuccessful(). */ void UMLListView::setStartedCut(bool startedCut) { m_bStartedCut = startedCut; } /** * Set the variable m_bStartedCopy. * NB: While m_bStartedCut is reset as soon as the Cut operation is done, * the variable m_bStartedCopy is reset much later - upon pasting. */ void UMLListView::setStartedCopy(bool startedCopy) { m_bStartedCopy = startedCopy; } /** * Return the variable m_bStartedCopy. */ bool UMLListView::startedCopy() const { return m_bStartedCopy; } /** * Returns the corresponding view if the listview type is one of the root views, * Root/Logical/UseCase/Component/Deployment/EntityRelation View. */ UMLListViewItem *UMLListView::rootView(UMLListViewItem::ListViewType type) { UMLListViewItem *theView = 0; switch (type) { case UMLListViewItem::lvt_View: theView = m_rv; break; case UMLListViewItem::lvt_Logical_View: theView = m_lv[Uml::ModelType::Logical]; break; case UMLListViewItem::lvt_UseCase_View: theView = m_lv[Uml::ModelType::UseCase]; break; case UMLListViewItem::lvt_Component_View: theView = m_lv[Uml::ModelType::Component]; break; case UMLListViewItem::lvt_Deployment_View: theView = m_lv[Uml::ModelType::Deployment]; break; case UMLListViewItem::lvt_EntityRelationship_Model: theView = m_lv[Uml::ModelType::EntityRelationship]; break; case UMLListViewItem::lvt_Datatype_Folder: // @todo fix asymmetric naming theView = m_datatypeFolder; break; default: break; } return theView; } /** * Deletes all child-items of @p parent. * Do it in reverse order, because of the index. */ void UMLListView::deleteChildrenOf(UMLListViewItem* parent) { if (!parent) { return; } if (parent == m_lv[Uml::ModelType::Logical]) { delete m_datatypeFolder; m_datatypeFolder = 0; } for (int i = parent->childCount() - 1; i >= 0; --i) parent->removeChild(parent->child(i)); } /** * */ void UMLListView::closeDatatypesFolder() { m_datatypeFolder->setOpen(false); } /** * Delete a listview item. * @param temp a non-null UMLListViewItem, for example: (UMLListViewItem*)currentItem() * @return true if correctly deleted */ bool UMLListView::deleteItem(UMLListViewItem *temp) { if (!temp) return false; UMLObject *object = temp->umlObject(); UMLListViewItem::ListViewType lvt = temp->type(); if (Model_Utils::typeIsDiagram(lvt)) { m_doc->removeDiagram(temp->ID()); } else if (temp == m_datatypeFolder) { // we can't delete the datatypeFolder because umbrello will crash without a special handling return false; } else if (Model_Utils::typeIsCanvasWidget(lvt) || Model_Utils::typeIsClassifierList(lvt)) { UMLPackage *nmSpc = object->asUMLPackage(); if (nmSpc) { UMLObjectList &contained = nmSpc->containedObjects(); if (contained.count()) { KMessageBox::error( 0, i18n("The folder must be emptied before it can be deleted."), i18n("Folder Not Empty")); return false; } } UMLCanvasObject *canvasObj = object->asUMLCanvasObject(); if (canvasObj) { // We cannot just delete canvasObj here: What if the object // is still being used by others (for example, as a parameter // or return type of an operation) ? // Deletion should not have been permitted in the first place // if the object still has users - but Umbrello is lacking // that logic. canvasObj->removeAllChildObjects(); } if (object) { UMLApp::app()->executeCommand(new Uml::CmdRemoveUMLObject(object)); // Physical deletion of `temp' will be done by Qt signal, see // UMLDoc::removeUMLObject() } else { delete temp; } } else { uWarning() << "mt_Delete called with unknown type"; } return true; } /** * Always allow starting a drag */ void UMLListView::dragEnterEvent(QDragEnterEvent* event) { event->accept(); } /** * Check drag destination and update move/copy action */ void UMLListView::dragMoveEvent(QDragMoveEvent* event) { // Check if drag destination is compatible with source if (acceptDrag(event)) { event->acceptProposedAction(); } else { event->ignore(); return; } } /** * */ void UMLListView::dropEvent(QDropEvent* event) { if (!acceptDrag(event)) { event->ignore(); } else { UMLListViewItem* target = static_cast(itemAt(event->pos())); if (!target) { DEBUG(DBG_SRC) << "itemAt(mousePoint) returns 0"; event->ignore(); return; } slotDropped(event, target); } } void UMLListView::commitData(QWidget *editor) { if (!editor) return; QModelIndex index = currentIndex(); if (!index.isValid()) return; QAbstractItemDelegate *delegate = itemDelegate(index); editor->removeEventFilter(delegate); QByteArray n = editor->metaObject()->userProperty().name(); if (n.isEmpty()) { DEBUG(DBG_SRC) << "no name property found in list view item editor"; return; } QString newText = editor->property(n).toString(); UMLListViewItem *item = dynamic_cast(currentItem()); if (!item) { DEBUG(DBG_SRC) << "no item found after editing model index" << index; return; } item->slotEditFinished(newText); editor->installEventFilter(delegate); } /** * Set the background color. * @param color the new background color */ void UMLListView::setBackgroundColor(const QColor & color) { QPalette palette; palette.setColor(backgroundRole(), color); setPalette(palette); } /** * Overloading operator for debugging output. */ QDebug operator<<(QDebug out, const UMLListView& view) { UMLListViewItem* header = static_cast(view.headerItem()); if (header) { out << *header; for(int indx = 0; indx < header->childCount(); ++indx) { UMLListViewItem* item = static_cast(header->child(indx)); if (item) { out << indx << " - " << *item << endl; } else { out << indx << " - " << "" << endl; } } } else { out << ""; } return out.space(); }