diff --git a/umbrello/CMakeLists.txt b/umbrello/CMakeLists.txt index 90c68876d..82e39959d 100644 --- a/umbrello/CMakeLists.txt +++ b/umbrello/CMakeLists.txt @@ -1,678 +1,679 @@ add_subdirectory( headings ) if(ENABLE_OBJECT_DIAGRAM) set(ACTION_NEW_OBJECT_DIAGRAM "") endif() configure_file(umbrelloui.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/umbrelloui.rc @ONLY) if(BUILD_KF5) configure_file(ui.qrc.cmake ${CMAKE_CURRENT_BINARY_DIR}/ui.qrc @ONLY) endif() ########### set variables ############# # php import support requires kdevplatform and kdev-php # which does not compile without NO_CAST_XX_ASCII if(NOT BUILD_PHP_IMPORT) add_definitions(-DQT_NO_CAST_TO_ASCII) add_definitions(-DQT_NO_CAST_FROM_ASCII) endif() # Some definitions for experimental code or debugging # TODO migrate debug settings to DEBUG_REGISTER macro #add_definitions(-DXMI_FLAT_PACKAGES) # umlobject #add_definitions(-DDEBUG_LVITEM_INSERTION_ORDER) # umllistviewitem #add_definitions(-DTRY_BUGFIX_120682) # model_utils #add_definitions(-DVERBOSE_DEBUGGING) # listpopupmenu, association, petaltree2uml, # umlobject, umldoc, classifierlistpage if(UNIX) add_definitions(-D_GLIBCXX_PERMIT_BACKWARD_HASH) endif() add_definitions(-DCMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}") add_definitions(-DDOCGENERATORS_DIR="${CMAKE_SOURCE_DIR}/umbrello/docgenerators") add_definitions(-DUMBRELLOUI_RC="${CMAKE_CURRENT_BINARY_DIR}/umbrelloui.rc") include_directories( ${LIBXML2_INCLUDE_DIR} ${LIBXSLT_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/clipboard/ ${CMAKE_CURRENT_SOURCE_DIR}/cmds ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/ada/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/as/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/cpp/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/csharp/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/d/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/idl/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/java/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/js/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/pascal/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/perl/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/php/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/python/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/ruby/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/sql/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/tcl/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/vala/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/xml/ ${CMAKE_CURRENT_SOURCE_DIR}/codegenwizard/ ${CMAKE_CURRENT_SOURCE_DIR}/codeimport/ ${CMAKE_CURRENT_SOURCE_DIR}/codeimport/csharp/ ${CMAKE_CURRENT_SOURCE_DIR}/codeimpwizard/ ${CMAKE_CURRENT_SOURCE_DIR}/debug/ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/pages/ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/widgets/ ${CMAKE_CURRENT_SOURCE_DIR}/docgenerators/ ${CMAKE_CURRENT_SOURCE_DIR}/finder/ ${CMAKE_CURRENT_SOURCE_DIR}/refactoring/ ${CMAKE_CURRENT_SOURCE_DIR}/uml1model/ ${CMAKE_CURRENT_SOURCE_DIR}/umlwidgets/ ${CMAKE_CURRENT_SOURCE_DIR}/menus ${CMAKE_SOURCE_DIR}/lib/cppparser/ ${CMAKE_SOURCE_DIR}/lib/interfaces/ ) set(libdebug_SRCS debug/debug_utils.cpp ) set(libcodegenerator_SRCS codegenerators/advancedcodegenerator.cpp codegenerators/classifiercodedocument.cpp codegenerators/codeaccessormethod.cpp codegenerators/codeblock.cpp codegenerators/codeblockwithcomments.cpp codegenerators/codeclassfield.cpp codegenerators/codeclassfielddeclarationblock.cpp codegenerators/codecomment.cpp codegenerators/codedocument.cpp codegenerators/codegenerationpolicy.cpp codegenerators/codegenerator.cpp codegenerators/codegenfactory.cpp codegenerators/codegenobjectwithtextblocks.cpp codegenerators/codegenpolicyext.cpp codegenerators/codegen_utils.cpp codegenerators/codemethodblock.cpp codegenerators/codeoperation.cpp codegenerators/codeparameter.cpp codegenerators/ada/adawriter.cpp codegenerators/as/aswriter.cpp codegenerators/cpp/cppcodeclassfield.cpp codegenerators/cpp/cppcodecomment.cpp codegenerators/cpp/cppcodedocumentation.cpp codegenerators/cpp/cppcodegenerationform.cpp codegenerators/cpp/cppcodegenerationpolicy.cpp codegenerators/cpp/cppcodegenerationpolicypage.cpp codegenerators/cpp/cppcodegenerator.cpp codegenerators/cpp/cppheaderclassdeclarationblock.cpp codegenerators/cpp/cppheadercodeaccessormethod.cpp codegenerators/cpp/cppheadercodeclassfielddeclarationblock.cpp codegenerators/cpp/cppheadercodedocument.cpp codegenerators/cpp/cppheadercodeoperation.cpp codegenerators/cpp/cppmakecodedocument.cpp codegenerators/cpp/cppsourcecodeaccessormethod.cpp codegenerators/cpp/cppsourcecodeclassfielddeclarationblock.cpp codegenerators/cpp/cppsourcecodedocument.cpp codegenerators/cpp/cppsourcecodeoperation.cpp codegenerators/cpp/cppwriter.cpp codegenerators/csharp/csharpwriter.cpp codegenerators/d/dclassdeclarationblock.cpp codegenerators/d/dclassifiercodedocument.cpp codegenerators/d/dcodeaccessormethod.cpp codegenerators/d/dcodeclassfield.cpp codegenerators/d/dcodeclassfielddeclarationblock.cpp codegenerators/d/dcodecomment.cpp codegenerators/d/dcodedocumentation.cpp codegenerators/d/dcodegenerationpolicy.cpp codegenerators/d/dcodegenerationpolicypage.cpp codegenerators/d/dcodegenerator.cpp codegenerators/d/dcodeoperation.cpp codegenerators/d/dwriter.cpp codegenerators/hierarchicalcodeblock.cpp codegenerators/idl/idlwriter.cpp codegenerators/java/javaantcodedocument.cpp codegenerators/java/javaclassdeclarationblock.cpp codegenerators/java/javaclassifiercodedocument.cpp codegenerators/java/javacodeaccessormethod.cpp codegenerators/java/javacodeclassfield.cpp codegenerators/java/javacodeclassfielddeclarationblock.cpp codegenerators/java/javacodecomment.cpp codegenerators/java/javacodedocumentation.cpp codegenerators/java/javacodegenerationpolicy.cpp codegenerators/java/javacodegenerationpolicypage.cpp codegenerators/java/javacodegenerator.cpp codegenerators/java/javacodeoperation.cpp codegenerators/java/javawriter.cpp codegenerators/js/jswriter.cpp codegenerators/ownedcodeblock.cpp codegenerators/ownedhierarchicalcodeblock.cpp codegenerators/pascal/pascalwriter.cpp codegenerators/perl/perlwriter.cpp codegenerators/php/php5writer.cpp codegenerators/php/phpwriter.cpp codegenerators/python/pythonwriter.cpp codegenerators/ruby/rubyclassdeclarationblock.cpp codegenerators/ruby/rubyclassifiercodedocument.cpp codegenerators/ruby/rubycodeaccessormethod.cpp codegenerators/ruby/rubycodeclassfield.cpp codegenerators/ruby/rubycodeclassfielddeclarationblock.cpp codegenerators/ruby/rubycodecomment.cpp codegenerators/ruby/rubycodedocumentation.cpp codegenerators/ruby/rubycodegenerationpolicy.cpp codegenerators/ruby/rubycodegenerationpolicypage.cpp codegenerators/ruby/rubycodegenerator.cpp codegenerators/ruby/rubycodeoperation.cpp codegenerators/ruby/rubywriter.cpp codegenerators/simplecodegenerator.cpp codegenerators/sql/mysqlwriter.cpp codegenerators/sql/postgresqlwriter.cpp codegenerators/sql/sqlwriter.cpp codegenerators/tcl/tclwriter.cpp codegenerators/textblock.cpp codegenerators/vala/valawriter.cpp codegenerators/xml/xmlcodecomment.cpp codegenerators/xml/xmlelementcodeblock.cpp codegenerators/xml/xmlschemawriter.cpp ) ki18n_wrap_ui( libcodegenerator_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/cpp/cppcodegenerationformbase.ui ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/d/dcodegenerationformbase.ui ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/java/javacodegenerationformbase.ui ${CMAKE_CURRENT_SOURCE_DIR}/codegenerators/ruby/rubycodegenerationformbase.ui ) set(libdocgenerator_SRCS docgenerators/docbook2xhtmlgeneratorjob.cpp docgenerators/docbookgenerator.cpp docgenerators/docbookgeneratorjob.cpp docgenerators/xhtmlgenerator.cpp ) set(libdialogs_SRCS dialogs/activitydialog.cpp dialogs/associationpropertiesdialog.cpp dialogs/classpropertiesdialog.cpp dialogs/classwizard.cpp dialogs/codeeditor.cpp dialogs/codetextedit.cpp dialogs/codetexthighlighter.cpp dialogs/codeviewerdialog.cpp dialogs/diagramselectiondialog.cpp dialogs/dialog_utils.cpp dialogs/dontaskagain.cpp dialogs/exportallviewsdialog.cpp dialogs/finddialog.cpp dialogs/messagewidgetpropertiesdialog.cpp dialogs/multipagedialogbase.cpp dialogs/notedialog.cpp dialogs/objectnodedialog.cpp dialogs/overwritedialog.cpp dialogs/parameterpropertiesdialog.cpp dialogs/selectoperationdialog.cpp dialogs/settingsdialog.cpp dialogs/singlepagedialogbase.cpp dialogs/statedialog.cpp dialogs/umlattributedialog.cpp dialogs/umlinstanceattributedialog.cpp dialogs/umlcheckconstraintdialog.cpp dialogs/umlentityattributedialog.cpp dialogs/umlenumliteraldialog.cpp dialogs/umlfiledialog.cpp dialogs/umlforeignkeyconstraintdialog.cpp dialogs/umloperationdialog.cpp dialogs/umlroledialog.cpp dialogs/umltemplatedialog.cpp dialogs/umluniqueconstraintdialog.cpp dialogs/umlviewdialog.cpp dialogs/pages/activitypage.cpp dialogs/pages/notepage.cpp dialogs/pages/associationgeneralpage.cpp dialogs/pages/associationrolepage.cpp dialogs/pages/autolayoutoptionpage.cpp dialogs/pages/classassociationspage.cpp dialogs/pages/classgeneralpage.cpp dialogs/pages/classifierlistpage.cpp dialogs/pages/classoptionspage.cpp dialogs/pages/codegenerationpolicypage.cpp dialogs/pages/codeimportoptionspage.cpp dialogs/pages/codevieweroptionspage.cpp dialogs/pages/constraintlistpage.cpp dialogs/pages/defaultcodegenpolicypage.cpp dialogs/pages/diagramprintpage.cpp dialogs/pages/diagrampropertiespage.cpp dialogs/pages/dialogpagebase.cpp dialogs/pages/generaloptionpage.cpp dialogs/pages/packagecontentspage.cpp dialogs/pages/selectoperationpage.cpp dialogs/pages/uioptionspage.cpp dialogs/pages/umlroleproperties.cpp dialogs/pages/umlwidgetstylepage.cpp dialogs/widgets/documentationwidget.cpp dialogs/widgets/imagetypewidget.cpp dialogs/widgets/resolutionwidget.cpp dialogs/widgets/umlartifacttypewidget.cpp dialogs/widgets/umldatatypewidget.cpp dialogs/widgets/defaultvaluewidget.cpp dialogs/widgets/umlobjectnamewidget.cpp dialogs/widgets/umlpackagewidget.cpp dialogs/widgets/umlstereotypewidget.cpp dialogs/widgets/visibilityenumwidget.cpp ) ki18n_wrap_ui( libdialogs_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/codeviewerdialogbase.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/codevieweroptionsbase.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/exportallviewsdialogbase.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/finddialog.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/pages/autolayoutoptionpage.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/pages/codeimportoptionspage.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/pages/diagrampropertiespage.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/pages/umlrolepropertiesbase.ui ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/umlinstanceattributedialog.ui ) set(librefactoring_SRCS refactoring/refactoringassistant.cpp ) set(libcodegenwizard_SRCS codegenwizard/codegenerationwizard.cpp codegenwizard/codegenoptionspage.cpp codegenwizard/codegenselectpage.cpp codegenwizard/codegenstatuspage.cpp ) ki18n_wrap_ui( libcodegenwizard_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/codegenwizard/codegenoptionspage.ui ${CMAKE_CURRENT_SOURCE_DIR}/codegenwizard/codegenselectpage.ui ${CMAKE_CURRENT_SOURCE_DIR}/codegenwizard/codegenstatuspage.ui ) set(libcodeimpwizard_SRCS codeimpwizard/codeimportingwizard.cpp codeimpwizard/codeimpselectpage.cpp codeimpwizard/codeimpstatuspage.cpp codeimpwizard/codeimpthread.cpp ) ki18n_wrap_ui( libcodeimpwizard_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/codeimpwizard/codeimpselectpage.ui ${CMAKE_CURRENT_SOURCE_DIR}/codeimpwizard/codeimpstatuspage.ui ) set(libcodeimport_SRCS codeimport/adaimport.cpp codeimport/classimport.cpp codeimport/idlimport.cpp codeimport/import_utils.cpp codeimport/javaimport.cpp codeimport/nativeimportbase.cpp codeimport/pascalimport.cpp codeimport/pythonimport.cpp codeimport/sqlimport.cpp codeimport/csharp/csharpimport.cpp ) if(BUILD_PHP_IMPORT) list(APPEND libcodeimport_SRCS codeimport/phpimport.cpp ) endif() list(APPEND libcodeimport_SRCS codeimport/cppimport.cpp ) set(libkdevcppparser_SRCS ${CMAKE_SOURCE_DIR}/lib/cppparser/ast.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/ast_utils.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/cachemanager.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/driver.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/errors.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/lexer.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/lexercache.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/lookup.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/parser.cpp ${CMAKE_SOURCE_DIR}/lib/cppparser/tree_parser.cpp ${CMAKE_SOURCE_DIR}/lib/interfaces/hashedstring.cpp codeimport/kdevcppparser/cpptree2uml.cpp ) set(libclipboard_SRCS clipboard/idchangelog.cpp clipboard/umlclipboard.cpp clipboard/umldragdata.cpp ) set(libcmds_SRCS cmds/cmdbaseobjectcommand.cpp cmds/cmdcreatediagram.cpp cmds/cmdhandlerename.cpp cmds/cmdremovediagram.cpp cmds/cmdsetstereotype.cpp cmds/cmdsetvisibility.cpp cmds/generic/cmdrenameumlinstancetype.cpp cmds/generic/cmdcreateumlobject.cpp cmds/generic/cmdremoveumlobject.cpp cmds/generic/cmdrenameumlobject.cpp cmds/widget/cmdbasewidgetcommand.cpp cmds/widget/cmdchangefont.cpp cmds/widget/cmdchangetextcolor.cpp cmds/widget/cmdchangelinecolor.cpp cmds/widget/cmdchangelinewidth.cpp cmds/widget/cmdchangefillcolor.cpp cmds/widget/cmdchangeusefillcolor.cpp cmds/widget/cmdchangemultiplicity.cpp cmds/widget/cmdchangevisualproperty.cpp cmds/widget/cmdcreatewidget.cpp cmds/widget/cmdmovewidget.cpp cmds/widget/cmdresizewidget.cpp cmds/widget/cmdremovewidget.cpp cmds/widget/cmdsetname.cpp cmds/widget/cmdsettxt.cpp ) set(libmenus_SRCS menus/listpopupmenu.cpp menus/umllistviewpopupmenu.cpp menus/umlscenepopupmenu.cpp menus/associationwidgetpopupmenu.cpp menus/widgetbasepopupmenu.cpp menus/dialogspopupmenu.cpp ) set(libumlwidgets_SRCS umlwidgets/activitywidget.cpp umlwidgets/actorwidget.cpp umlwidgets/artifactwidget.cpp umlwidgets/associationline.cpp umlwidgets/associationwidget.cpp umlwidgets/boxwidget.cpp umlwidgets/categorywidget.cpp umlwidgets/childwidgetplacement.cpp umlwidgets/childwidgetplacementpin.cpp umlwidgets/childwidgetplacementport.cpp umlwidgets/classifierwidget.cpp umlwidgets/combinedfragmentwidget.cpp umlwidgets/componentwidget.cpp umlwidgets/datatypewidget.cpp umlwidgets/entitywidget.cpp umlwidgets/enumwidget.cpp umlwidgets/floatingdashlinewidget.cpp umlwidgets/floatingtextwidget.cpp umlwidgets/forkjoinwidget.cpp + umlwidgets/interfacewidget.cpp umlwidgets/layoutgrid.cpp umlwidgets/linkwidget.cpp umlwidgets/messagewidget.cpp umlwidgets/nodewidget.cpp umlwidgets/notewidget.cpp umlwidgets/objectnodewidget.cpp umlwidgets/objectwidget.cpp umlwidgets/packagewidget.cpp umlwidgets/pinportbase.cpp umlwidgets/pinwidget.cpp umlwidgets/portwidget.cpp umlwidgets/preconditionwidget.cpp umlwidgets/regionwidget.cpp umlwidgets/seqlinewidget.cpp umlwidgets/signalwidget.cpp umlwidgets/statewidget.cpp umlwidgets/toolbarstateonewidget.cpp umlwidgets/umlwidget.cpp umlwidgets/usecasewidget.cpp umlwidgets/widget_factory.cpp umlwidgets/widget_utils.cpp umlwidgets/widgetbase.cpp umlwidgets/widgetlist_utils.cpp umlwidgets/statusbartoolbutton.cpp ) set(libfinder_SRCS finder/findresults.cpp finder/umldocfinder.cpp finder/umlfinder.cpp finder/umllistviewfinder.cpp finder/umlscenefinder.cpp ) set(libuml_SRCS uml1model/actor.cpp uml1model/artifact.cpp uml1model/association.cpp uml1model/attribute.cpp uml1model/category.cpp uml1model/checkconstraint.cpp uml1model/classifier.cpp uml1model/classifierlistitem.cpp uml1model/component.cpp uml1model/datatype.cpp uml1model/entity.cpp uml1model/entityattribute.cpp uml1model/entityconstraint.cpp uml1model/enum.cpp uml1model/enumliteral.cpp uml1model/folder.cpp uml1model/foreignkeyconstraint.cpp uml1model/node.cpp uml1model/operation.cpp uml1model/package.cpp uml1model/port.cpp uml1model/stereotype.cpp uml1model/template.cpp uml1model/umlattributelist.cpp uml1model/umlcanvasobject.cpp uml1model/umlclassifierlistitemlist.cpp uml1model/umlentityattributelist.cpp uml1model/umlentityconstraintlist.cpp uml1model/umlobject.cpp uml1model/umlobjectlist.cpp uml1model/umlrole.cpp uml1model/usecase.cpp uml1model/uniqueconstraint.cpp uml1model/instance.cpp uml1model/instanceattribute.cpp ) set(umbrellobase_SRCS assocrules.cpp basictypes.cpp birdview.cpp codeviewerstate.cpp cmdlineexportallviewsevent.cpp diagramswindow.cpp diagram_utils.cpp objectswindow.cpp docwindow.cpp dotgenerator.cpp icon_utils.cpp import_argo.cpp import_rose.cpp layoutgenerator.cpp model_utils.cpp object_factory.cpp optionstate.cpp petalnode.cpp petaltree2uml.cpp stereotypeswindow.cpp toolbarstatearrow.cpp toolbarstateassociation.cpp toolbarstate.cpp toolbarstatefactory.cpp toolbarstatemessages.cpp toolbarstateother.cpp toolbarstatepool.cpp umlappprivate.cpp uml.cpp umldoc.cpp umllistview.cpp umllistviewitem.cpp umlscene.cpp umlview.cpp umlviewimageexporterall.cpp umlviewimageexporter.cpp umlviewimageexportermodel.cpp uniqueid.cpp worktoolbar.cpp ) set(umbrellomodels_SRCS models/diagramsmodel.cpp models/objectsmodel.cpp models/stereotypesmodel.cpp ) kconfig_add_kcfg_files(umbrellobase_SRCS umbrellosettings.kcfgc) set(libumbrello_SRCS ${libdebug_SRCS} ${libdialogs_SRCS} ${libfinder_SRCS} ${librefactoring_SRCS} ${libcodegenwizard_SRCS} ${libcodeimpwizard_SRCS} ${libclassparser_SRCS} ${libclipboard_SRCS} ${libkdevcppparser_SRCS} ${libcodeimport_SRCS} ${libcodegenerator_SRCS} ${libdocgenerator_SRCS} ${libcmds_SRCS} ${libmenus_SRCS} ${libuml_SRCS} ${libumlwidgets_SRCS} ${umbrellobase_SRCS} ${umbrellomodels_SRCS} ) set(umbrello_SRCS main.cpp ) set(LIB_BUILD_MODE STATIC) if(NOT BUILD_KF5) if(CMAKE_MAJOR_VERSION LESS 3) qt4_add_resources(libumbrello_SRCS icons.qrc) else() list(APPEND libumbrello_SRCS icons.qrc) endif() kde4_add_library(libumbrello ${LIB_BUILD_MODE} ${libumbrello_SRCS}) set_target_properties(libumbrello PROPERTIES OUTPUT_NAME umbrello) target_link_libraries(libumbrello Qt4::QtCore Qt4::QtGui Qt4::QtXml Qt4::QtWebKit ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_KFILE_LIBS} ) if(BUILD_PHP_IMPORT) target_link_libraries(libumbrello ${KDEVPLATFORM_INTERFACES_LIBRARIES} ${KDEVPLATFORM_LANGUAGE_LIBRARIES} ${KDEVPLATFORM_OUTPUTVIEW_LIBRARIES} ${KDEVPLATFORM_PROJECT_LIBRARIES} ${KDEVPLATFORM_SUBLIME_LIBRARIES} ${KDEVPLATFORM_SHELL_LIBRARIES} ${KDEVPLATFORM_UTIL_LIBRARIES} ${KDEVPLATFORM_VCS_LIBRARIES} ${KDEVPLATFORM_DEBUGGER_LIBRARIES} ${KDEVPLATFORM_DOCUMENTATION_LIBRARIES} ${KDEVPLATFORM_TESTS_LIBRARIES} ${KDEVPLATFORM_JSONTESTS_LIBRARIES} kdev4phpparser ) endif() kde4_add_app_icon(umbrello_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/pics/global/kde4/hi*-apps-umbrello.png") kde4_add_executable(umbrello ${umbrello_SRCS}) target_link_libraries(umbrello ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_KFILE_LIBS} libumbrello) else() if(CMAKE_MAJOR_VERSION LESS 3) qt5_add_resources(libumbrello_SRCS icons.qrc ${CMAKE_CURRENT_BINARY_DIR}/ui.qrc) else() list(APPEND libumbrello_SRCS icons.qrc ${CMAKE_CURRENT_BINARY_DIR}/ui.qrc) endif() add_library(libumbrello ${LIB_BUILD_MODE} ${libumbrello_SRCS}) set_target_properties(libumbrello PROPERTIES OUTPUT_NAME umbrello) target_link_libraries(libumbrello Qt5::Widgets Qt5::Xml Qt5::PrintSupport Qt5::Svg Qt5::WebKitWidgets KF5::Archive KF5::Completion KF5::CoreAddons KF5::I18n KF5::IconThemes KF5::KIOCore KF5::KDELibs4Support KF5::TextEditor KF5::WidgetsAddons KF5::XmlGui KF5::Crash ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES} ) if(BUILD_PHP_IMPORT) target_link_libraries(libumbrello KDev::Interfaces KDev::Language KDev::Tests kdevphpparser ) endif() ecm_add_app_icon(umbrello_SRCS ICONS ${CMAKE_CURRENT_SOURCE_DIR}/pics/global/16-apps-umbrello.png ${CMAKE_CURRENT_SOURCE_DIR}/pics/global/22-apps-umbrello.png ${CMAKE_CURRENT_SOURCE_DIR}/pics/global/32-apps-umbrello.png ${CMAKE_CURRENT_SOURCE_DIR}/pics/global/48-apps-umbrello.png ${CMAKE_CURRENT_SOURCE_DIR}/pics/global/64-apps-umbrello.png ${CMAKE_CURRENT_SOURCE_DIR}/pics/global/128-apps-umbrello.png ) add_executable(umbrello ${umbrello_SRCS}) target_link_libraries(umbrello libumbrello KF5::Crash KF5::WindowSystem KF5::KDELibs4Support ) set_target_properties(umbrello PROPERTIES OUTPUT_NAME umbrello5) endif() if(LIB_BUILD_MODE EQUAL SHARED) install(TARGETS libumbrello ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif() install(TARGETS umbrello ${INSTALL_TARGETS_DEFAULT_ARGS} ) ########### install files ############# if(NOT BUILD_KF5) install( PROGRAMS org.kde.umbrello.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/umbrelloui.rc DESTINATION ${UMBRELLO_DATA_INSTALL_DIR} ) else() file(READ org.kde.umbrello.desktop UMBRELLO_DESKTOP_OUT) string(REPLACE "Exec=umbrello" "Exec=umbrello5" UMBRELLO_DESKTOP_OUT "${UMBRELLO_DESKTOP_OUT}") file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/org.kde.umbrello.desktop "${UMBRELLO_DESKTOP_OUT}") install( PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.umbrello.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) install(FILES org.kde.umbrello.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) endif() install( FILES docgenerators/xmi2docbook.xsl docgenerators/docbook2xhtml.xsl docgenerators/xmi.css docgenerators/common.ent DESTINATION ${UMBRELLO_DATA_INSTALL_DIR} ) install( DIRECTORY layouts DESTINATION ${UMBRELLO_DATA_INSTALL_DIR} PATTERN .svn EXCLUDE ) add_subdirectory( pics ) diff --git a/umbrello/menus/widgetbasepopupmenu.cpp b/umbrello/menus/widgetbasepopupmenu.cpp index e6195fed8..c88211bcb 100644 --- a/umbrello/menus/widgetbasepopupmenu.cpp +++ b/umbrello/menus/widgetbasepopupmenu.cpp @@ -1,679 +1,680 @@ /*************************************************************************** * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * copyright (C) 2018 * * Umbrello UML Modeller Authors * ***************************************************************************/ #include "widgetbasepopupmenu.h" // app includes #include "activitywidget.h" #include "category.h" #include "classifier.h" #include "combinedfragmentwidget.h" #include "debug_utils.h" #include "entitywidget.h" #include "floatingtextwidget.h" #include "forkjoinwidget.h" +#include "interfacewidget.h" #include "notewidget.h" #include "objectwidget.h" #include "objectnodewidget.h" #include "pinportbase.h" #include "statewidget.h" #include "uml.h" #include "umllistview.h" #include "umlscene.h" // kde includes #include static const bool CHECKABLE = true; /** * Constructs the popup menu for a scene widget. * * @param parent The parent to ListPopupMenu. * @param widget The WidgetBase to represent a menu for. * @param multi True if multiple items are selected. * @param uniqueType The type of widget shared by all selected widgets */ WidgetBasePopupMenu::WidgetBasePopupMenu(QWidget * parent, WidgetBase * widget, bool multi, WidgetBase::WidgetType uniqueType) : ListPopupMenu(parent) { if (!widget) return; if (multi) { insertMultiSelectionMenu(uniqueType); } else { insertSingleSelectionMenu(widget); } bool bCutState = UMLApp::app()->isCutCopyState(); setActionEnabled(mt_Cut, bCutState); setActionEnabled(mt_Copy, bCutState); bool pasteAvailable = false; if (widget->isNoteWidget() && UMLApp::app()->listView()->startedCopy()) { NoteWidget::s_pCurrentNote = widget->asNoteWidget(); pasteAvailable = true; } setActionEnabled(mt_Paste, pasteAvailable); setActionChecked(mt_AutoResize, widget->autoResize()); setupActionsData(); } /** * Creates the "Show" submenu in the context menu of one classifier widget */ void WidgetBasePopupMenu::makeClassifierShowPopup(ClassifierWidget *c) { WidgetBase::WidgetType type = c->baseType(); KMenu* show = newMenu(i18n("Show"), this); show->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Show)); #ifdef ENABLE_WIDGET_SHOW_DOC insert(mt_Show_Documentation, show, i18n("Documentation"), CHECKABLE); setActionChecked(mt_Show_Documentation, c->visualProperty(ClassifierWidget::ShowDocumentation)); #endif if (type == WidgetBase::wt_Class) { insert(mt_Show_Attributes, show, i18n("Attributes"), CHECKABLE); setActionChecked(mt_Show_Attributes, c->visualProperty(ClassifierWidget::ShowAttributes)); } insert(mt_Show_Operations, show, i18n("Operations"), CHECKABLE); setActionChecked(mt_Show_Operations, c->visualProperty(ClassifierWidget::ShowOperations)); insert(mt_Show_Public_Only, show, i18n("Public Only"), CHECKABLE); setActionChecked(mt_Show_Public_Only, c->visualProperty(ClassifierWidget::ShowPublicOnly)); insert(mt_Visibility, show, i18n("Visibility"), CHECKABLE); setActionChecked(mt_Visibility, c->visualProperty(ClassifierWidget::ShowVisibility)); insert(mt_Show_Operation_Signature, show, i18n("Operation Signature"), CHECKABLE); bool sig = (c->operationSignature() == Uml::SignatureType::SigNoVis || c->operationSignature() == Uml::SignatureType::ShowSig); setActionChecked(mt_Show_Operation_Signature, sig); if (type == WidgetBase::wt_Class) { insert(mt_Show_Attribute_Signature, show, i18n("Attribute Signature"), CHECKABLE); sig = (c->attributeSignature() == Uml::SignatureType::SigNoVis || c->attributeSignature() == Uml::SignatureType::ShowSig); setActionChecked(mt_Show_Attribute_Signature, sig); } insert(mt_Show_Packages, show, i18n("Package"), CHECKABLE); setActionChecked(mt_Show_Packages, c->visualProperty(ClassifierWidget::ShowPackage)); insert(mt_Show_Stereotypes, show, i18n("Stereotype"), CHECKABLE); setActionChecked(mt_Show_Stereotypes, c->visualProperty(ClassifierWidget::ShowStereotype)); addMenu(show); } /** * Creates the "Show" submenu the context menu of multiple classifier widgets */ void WidgetBasePopupMenu::makeMultiClassifierShowPopup(WidgetBase::WidgetType type) { KMenu* show = newMenu(i18n("Show"), this); show->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Show)); KMenu* attributes = newMenu(i18n("Attributes"), this); if (type == WidgetBase::wt_Class) { insert(mt_Show_Attributes_Selection, attributes, i18n("Show")); insert(mt_Hide_Attributes_Selection, attributes, i18n("Hide")); insert(mt_Show_Attribute_Signature_Selection, attributes, i18n("Show Signatures")); insert(mt_Hide_Attribute_Signature_Selection, attributes, i18n("Hide Signatures")); } show->addMenu(attributes); KMenu* operations = newMenu(i18n("Operations"), this); insert(mt_Show_Operations_Selection, operations, i18n("Show")); insert(mt_Hide_Operations_Selection, operations, i18n("Hide")); insert(mt_Show_Operation_Signature_Selection, operations, i18n("Show Signatures")); insert(mt_Hide_Operation_Signature_Selection, operations, i18n("Hide Signatures")); show->addMenu(operations); KMenu* visibility = newMenu(i18n("Visibility"), this); insert(mt_Show_Visibility_Selection, visibility, i18n("Show")); insert(mt_Hide_Visibility_Selection, visibility, i18n("Hide")); insert(mt_Hide_NonPublic_Selection, visibility, i18n("Hide Non-public members")); insert(mt_Show_NonPublic_Selection, visibility, i18n("Show Non-public members")); show->addMenu(visibility); KMenu* packages = newMenu(i18n("Packages"), this); insert(mt_Show_Packages_Selection, packages, i18n("Show")); insert(mt_Hide_Packages_Selection, packages, i18n("Hide")); show->addMenu(packages); if (type == WidgetBase::wt_Class) { KMenu* stereotypes = newMenu(i18n("Stereotypes"), this); insert(mt_Show_Stereotypes_Selection, stereotypes, i18n("Show")); insert(mt_Hide_Stereotypes_Selection, stereotypes, i18n("Hide")); show->addMenu(stereotypes); } addMenu(show); } /** * Inserts the menu actions for a widget * * @param widget widget to generate the menu for */ void WidgetBasePopupMenu::insertSingleSelectionMenu(WidgetBase* widget) { WidgetBase::WidgetType type = widget->baseType(); switch (type) { case WidgetBase::wt_Actor: case WidgetBase::wt_UseCase: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Category: { insertSubMenuNew(type); insertSubMenuCategoryType(widget->umlObject()->asUMLCategory()); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); break; } case WidgetBase::wt_Class: { ClassifierWidget* c = widget->asClassifierWidget(); if (!c) break; insertSubMenuNew(type); makeClassifierShowPopup(c); insertSubMenuColor(c->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); if (c->umlObject() && c->umlObject()->stereotype() == QLatin1String("class-or-package")) { insert(mt_ChangeToClass, i18n("Change into Class")); insert(mt_ChangeToPackage, i18n("Change into Package")); } else { insert(mt_Refactoring, Icon_Utils::SmallIcon(Icon_Utils::it_Refactor), i18n("Refactor")); insert(mt_ViewCode, Icon_Utils::SmallIcon(Icon_Utils::it_View_Code), i18n("View Code")); UMLClassifier *umlc = c->classifier(); if (umlc->isAbstract() && umlc->getAttributeList().size() == 0) insert(mt_ChangeToInterface, i18n("Change into Interface")); } insert(mt_Properties); } break; case WidgetBase::wt_Interface: { - ClassifierWidget* c = widget->asClassifierWidget(); + InterfaceWidget* c = widget->asInterfaceWidget(); if (!c) break; insertSubMenuNew(type); makeClassifierShowPopup(c); insertSubMenuColor(c->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_DrawAsCircle, i18n("Draw as Circle"), CHECKABLE); setActionChecked(mt_DrawAsCircle, c->visualProperty(ClassifierWidget::DrawAsCircle)); insert(mt_ChangeToClass, i18n("Change into Class")); insert(mt_Properties); } break; case WidgetBase::wt_Instance: insertSubMenuNew(type); insert(mt_InstanceAttribute); insert(mt_Rename_Object); insert(mt_Rename, i18n("Rename Class...")); insertStdItems(true, type); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Enum: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Entity: insertSubMenuNew(type); insertSubMenuShowEntity(widget->asEntityWidget()); insertSubMenuColor(widget->useFillColor()); insertStdItems(true, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Datatype: case WidgetBase::wt_Package: case WidgetBase::wt_Component: case WidgetBase::wt_Node: case WidgetBase::wt_Artifact: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(false, type); insert(mt_Rename); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Port: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(false); insert(mt_NameAsTooltip, i18n("Name as Tooltip"), true); { PinPortBase *pW = static_cast(widget); FloatingTextWidget *ft = pW->floatingTextWidget(); if (ft == 0) m_actions[mt_NameAsTooltip]->setChecked(true); } insert(mt_Delete); insert(mt_Properties); break; case WidgetBase::wt_Object: //Used for sequence diagram and collaboration diagram widgets insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); if (widget->umlScene() && widget->umlScene()->type() == Uml::DiagramType::Sequence) { addSeparator(); MenuType tabUp = mt_Up; insert(mt_Up, Icon_Utils::SmallIcon(Icon_Utils::it_Arrow_Up), i18n("Move Up")); insert(mt_Down, Icon_Utils::SmallIcon(Icon_Utils::it_Arrow_Down), i18n("Move Down")); if (!(static_cast(widget))->canTabUp()) { setActionEnabled(tabUp, false); } } insertStdItems(true, type); insert(mt_Rename_Object); insert(mt_Rename, i18n("Rename Class...")); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Message: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); insertStdItems(false, type); //insert(mt_Change_Font); //insert(mt_Operation, Icon_Utils::SmallIcon(Icon_Utils::it_Operation_New), i18n("New Operation...")); //insert(mt_Select_Operation, i18n("Select Operation...")); break; case WidgetBase::wt_Note: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); insert(mt_Clear, Icon_Utils::SmallIcon(Icon_Utils::it_Clear), i18nc("clear note", "Clear")); addSeparator(); insert(mt_Rename, i18n("Change Text...")); insert(mt_Resize); insert(mt_AutoResize, i18n("Auto resize"), CHECKABLE); insert(mt_Delete); insert(mt_Change_Font); insert(mt_Properties); break; case WidgetBase::wt_Box: insertSubMenuNew(type); insertStdItems(false, type); insert(mt_Line_Color); break; case WidgetBase::wt_State: { StateWidget* pState = static_cast< StateWidget *>(widget); if (pState->stateType() == StateWidget::Normal) { // FIXME: why not using wt_state insertSubMenuNew(WidgetBase::wt_Activity); } else { insertSubMenuNew(type); } insertSubMenuColor(widget->useFillColor()); insertStdItems(false, type); switch (pState->stateType()) { case StateWidget::Normal: insert(mt_Rename, i18n("Change State Name...")); insert(mt_Change_Font); insert(mt_Properties); break; case StateWidget::Fork: case StateWidget::Join: if (pState->drawVertical()) insert(mt_Flip, i18n("Flip Horizontal")); else insert(mt_Flip, i18n("Flip Vertical")); break; default: break; } } break; case WidgetBase::wt_ForkJoin: insertSubMenuNew(type); { ForkJoinWidget *pForkJoin = static_cast(widget); if (pForkJoin->orientation() == Qt::Vertical) { insert(mt_Flip, i18n("Flip Horizontal")); } else { insert(mt_Flip, i18n("Flip Vertical")); } m_actions[mt_Fill_Color] = addAction(Icon_Utils::SmallIcon(Icon_Utils::it_Color_Fill), i18n("Fill Color...")); } break; case WidgetBase::wt_Activity: insertSubMenuNew(type); { ActivityWidget* pActivity = static_cast(widget); if(pActivity->activityType() == ActivityWidget::Normal || pActivity->activityType() == ActivityWidget::Invok || pActivity->activityType() == ActivityWidget::Param) { insertSubMenuColor(widget->useFillColor()); } insertStdItems(false, type); if(pActivity->activityType() == ActivityWidget::Normal || pActivity->activityType() == ActivityWidget::Invok || pActivity->activityType() == ActivityWidget::Param) { insert(mt_Rename, i18n("Change Activity Name...")); insert(mt_Change_Font); insert(mt_Properties); } } break; case WidgetBase::wt_ObjectNode: insertSubMenuNew(type); { ObjectNodeWidget* objWidget = static_cast(widget); if (objWidget->objectNodeType() == ObjectNodeWidget::Buffer || objWidget->objectNodeType() == ObjectNodeWidget::Data || objWidget->objectNodeType() == ObjectNodeWidget::Flow) { insertSubMenuColor(widget->useFillColor()); } insertStdItems(false, type); if (objWidget->objectNodeType() == ObjectNodeWidget::Buffer || objWidget->objectNodeType() == ObjectNodeWidget::Data || objWidget->objectNodeType() == ObjectNodeWidget::Flow) { insert(mt_Rename, i18n("Change Object Node Name...")); insert(mt_Change_Font); insert(mt_Properties); } } break; case WidgetBase::wt_Pin: case WidgetBase::wt_Signal: case WidgetBase::wt_FloatingDashLine: case WidgetBase::wt_Precondition: insertSubMenuNew(type); insertSubMenuColor(widget->useFillColor()); addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); insert(mt_Clear, Icon_Utils::SmallIcon(Icon_Utils::it_Clear), i18nc("clear precondition", "Clear")); addSeparator(); insert(mt_Rename, i18n("Change Text...")); if (type == WidgetBase::wt_Pin) { insert(mt_NameAsTooltip, i18n("Name as Tooltip"), true); PinPortBase *pW = static_cast(widget); FloatingTextWidget *ft = pW->floatingTextWidget(); if (ft == 0) m_actions[mt_NameAsTooltip]->setChecked(true); } insert(mt_Delete); insert(mt_Change_Font); break; case WidgetBase::wt_CombinedFragment: insertSubMenuNew(type); // for alternative and parallel combined fragments if ((static_cast(widget))->combinedFragmentType() == CombinedFragmentWidget::Alt || (static_cast(widget))->combinedFragmentType() == CombinedFragmentWidget::Par) { insert(mt_AddInteractionOperand, i18n("Add Interaction Operand")); addSeparator(); } insertSubMenuColor(widget->useFillColor()); addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); insert(mt_Clear, Icon_Utils::SmallIcon(Icon_Utils::it_Clear), i18nc("clear combined fragment", "Clear")); addSeparator(); insert(mt_Rename, i18n("Change Text...")); insert(mt_Delete); insert(mt_Change_Font); break; case WidgetBase::wt_Text: insertSubMenuNew(type); switch((static_cast(widget))->textRole()) { case Uml::TextRole::MultiB: insertAssociationTextItem(i18n("Change Multiplicity..."), mt_Rename_MultiB); break; case Uml::TextRole::MultiA: insertAssociationTextItem(i18n("Change Multiplicity..."), mt_Rename_MultiA); break; case Uml::TextRole::Name: insertAssociationTextItem(i18n("Change Name"), mt_Rename_Name); break; case Uml::TextRole::RoleAName: insertAssociationTextItem(i18n("Change Role A Name..."), mt_Rename_RoleAName); break; case Uml::TextRole::RoleBName: insertAssociationTextItem(i18n("Change Role B Name..."), mt_Rename_RoleBName); break; case Uml::TextRole::ChangeA: case Uml::TextRole::ChangeB: insert(mt_Change_Font); insert(mt_Reset_Label_Positions); insert(mt_Properties); break; case Uml::TextRole::Coll_Message_Self: case Uml::TextRole::Coll_Message: case Uml::TextRole::Seq_Message_Self: case Uml::TextRole::Seq_Message: insert(mt_Change_Font); insert(mt_Operation, Icon_Utils::SmallIcon(Icon_Utils::it_Operation_New), i18n("New Operation...")); insert(mt_Select_Operation, i18n("Select Operation...")); break; case Uml::TextRole::Floating: default: insertStdItems(false, type); insert(mt_Rename, i18n("Change Text...")); insert(mt_Change_Font); break; } break; default: uWarning() << "unhandled WidgetType " << WidgetBase::toString(type); break; }//end switch } /** * Inserts the menu actions that work on the whole selection of widgets */ void WidgetBasePopupMenu::insertMultiSelectionMenu(WidgetBase::WidgetType uniqueType) { insertSubMenuAlign(); KMenu* color = newMenu(i18nc("color menu", "Color"), this); insert(mt_Line_Color_Selection, color, Icon_Utils::SmallIcon(Icon_Utils::it_Color_Line), i18n("Line Color...")); insert(mt_Fill_Color_Selection, color, Icon_Utils::SmallIcon(Icon_Utils::it_Color_Fill), i18n("Fill Color...")); insert(mt_Set_Use_Fill_Color_Selection, color, i18n("Use Fill Color")); insert(mt_Unset_Use_Fill_Color_Selection, color, i18n("No Fill Color")); // Add menu actions specific to classifiers if (uniqueType == WidgetBase::wt_Class || uniqueType == WidgetBase::wt_Interface) { makeMultiClassifierShowPopup(uniqueType); } addMenu(color); addSeparator(); insert(mt_Cut); insert(mt_Copy); addSeparator(); insert(mt_Clone); insert(mt_Delete); insert(mt_Resize); addSeparator(); insert(mt_Change_Font_Selection, Icon_Utils::SmallIcon(Icon_Utils::it_Change_Font), i18n("Change Font...")); } /** * Shortcut for the frequently used insert() calls. * * @param insertLeadingSeparator Set this true if the group shall * start with a separator. * @param type The WidgetType for which to insert the menu items. * If no argument is supplied then a Rename item will be * included. */ void WidgetBasePopupMenu::insertStdItems(bool insertLeadingSeparator, WidgetBase::WidgetType type) { if (insertLeadingSeparator) addSeparator(); insert(mt_Cut); insert(mt_Copy); insert(mt_Paste); addSeparator(); if (type == WidgetBase::wt_UMLWidget) insert(mt_Rename); else if (Model_Utils::isCloneable(type)) { insert(mt_Clone); insert(mt_Remove); } else insert(mt_Delete); insert(mt_Resize); insert(mt_AutoResize, i18n("Auto resize"), CHECKABLE); } /** * Add the align actions submenu */ void WidgetBasePopupMenu::insertSubMenuAlign() { KMenu* alignment = newMenu(i18nc("align menu", "Align"), this); insert(mt_Align_Right, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Right), i18n("Align Right")); insert(mt_Align_Left, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Left), i18n("Align Left")); insert(mt_Align_Top, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Top), i18n("Align Top")); insert(mt_Align_Bottom, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_Bottom), i18n("Align Bottom")); insert(mt_Align_VerticalMiddle, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_VerticalMiddle), i18n("Align Vertical Middle")); insert(mt_Align_HorizontalMiddle, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_HorizontalMiddle), i18n("Align Horizontal Middle")); insert(mt_Align_VerticalDistribute, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_VerticalDistribute), i18n("Align Vertical Distribute")); insert(mt_Align_HorizontalDistribute, alignment, Icon_Utils::SmallIcon(Icon_Utils::it_Align_HorizontalDistribute), i18n("Align Horizontal Distribute")); addMenu(alignment); } /** * Shortcut for commonly used sub menu initializations. * * @param fc The "Use Fill Color" is checked. */ void WidgetBasePopupMenu::insertSubMenuColor(bool fc) { KMenu* color = newMenu(i18nc("color menu", "Color"), this); insert(mt_Line_Color, color, Icon_Utils::SmallIcon(Icon_Utils::it_Color_Line), i18n("Line Color...")); insert(mt_Fill_Color, color, Icon_Utils::SmallIcon(Icon_Utils::it_Color_Fill), i18n("Fill Color...")); insert(mt_Use_Fill_Color, color, i18n("Use Fill Color"), CHECKABLE); setActionChecked(mt_Use_Fill_Color, fc); addMenu(color); } /** * Shortcut for commonly used sub menu initializations. * * @param type The widget type for which to set up the menu. */ void WidgetBasePopupMenu::insertSubMenuNew(WidgetBase::WidgetType type, KMenu *menu) { if (!menu) menu = makeNewMenu(); switch (type) { case WidgetBase::wt_Actor: case WidgetBase::wt_UseCase: insert(mt_Actor, menu); insert(mt_UseCase, menu); break; case WidgetBase::wt_Component: insert(mt_Component, menu); if (Settings::optionState().generalState.uml2) insert(mt_Port, menu); insert(mt_Artifact, menu); break; case WidgetBase::wt_Class: insert(mt_Attribute, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Public_Attribute), i18n("Attribute...")); insert(mt_Operation, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Public_Method), i18n("Operation...")); insert(mt_Template, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Template_New), i18n("Template...")); insert(mt_Class, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Class), i18nc("new class menu item", "Class...")); insert(mt_Interface, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Interface), i18n("Interface...")); insert(mt_Datatype, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Datatype), i18n("Datatype...")); insert(mt_Enum, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Enum), i18n("Enum...")); break; case WidgetBase::wt_Interface: insert(mt_Operation, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Public_Method), i18n("Operation...")); insert(mt_Template, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Template_New), i18n("Template...")); insert(mt_Class, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Class), i18nc("new class menu item", "Class...")); insert(mt_Interface, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Interface), i18n("Interface...")); insert(mt_Datatype, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Datatype), i18n("Datatype...")); insert(mt_Enum, menu, Icon_Utils::SmallIcon(Icon_Utils::it_Enum), i18n("Enum...")); break; case WidgetBase::wt_Entity: insert(mt_EntityAttribute, menu); insert(mt_PrimaryKeyConstraint, menu); insert(mt_UniqueConstraint, menu); insert(mt_ForeignKeyConstraint, menu); insert(mt_CheckConstraint, menu); break; case WidgetBase::wt_Enum: insert(mt_EnumLiteral, menu); break; default: break; } insert(mt_Note, menu); insert(mt_FloatText, menu); addMenu(menu); } void WidgetBasePopupMenu::insertSubMenuShowEntity(EntityWidget *widget) { KMenu* show = newMenu(i18n("Show"), this); show->setIcon(Icon_Utils::SmallIcon(Icon_Utils::it_Show)); insert(mt_Show_Attribute_Signature, show, i18n("Attribute Signature"), CHECKABLE); setActionChecked(mt_Show_Attribute_Signature, widget->showAttributeSignature()); insert(mt_Show_Stereotypes, show, i18n("Stereotype"), CHECKABLE); setActionChecked(mt_Show_Stereotypes, widget->showStereotype()); addMenu(show); } diff --git a/umbrello/umlscene.cpp b/umbrello/umlscene.cpp index d05fe586b..d5f9da4ee 100644 --- a/umbrello/umlscene.cpp +++ b/umbrello/umlscene.cpp @@ -1,4272 +1,4276 @@ /*************************************************************************** * 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 "umlscene.h" // application specific includes #include "activitywidget.h" #include "actorwidget.h" #include "artifactwidget.h" #include "association.h" #include "associationwidget.h" #include "assocrules.h" #include "attribute.h" #include "boxwidget.h" #include "classifier.h" #include "classifierwidget.h" #include "classoptionspage.h" #include "component.h" #include "cmds.h" #include "componentwidget.h" #include "datatype.h" #include "diagram_utils.h" #include "pinportbase.h" #include "datatypewidget.h" #include "debug_utils.h" #include "dialog_utils.h" #include "docwindow.h" #include "entity.h" #include "entitywidget.h" #include "enumwidget.h" #include "floatingtextwidget.h" #include "folder.h" #include "foreignkeyconstraint.h" #include "forkjoinwidget.h" #include "idchangelog.h" +#include "interfacewidget.h" #include "import_utils.h" #include "layoutgenerator.h" #include "layoutgrid.h" #include "messagewidget.h" #include "model_utils.h" #include "notewidget.h" #include "object_factory.h" #include "objectnodewidget.h" #include "objectwidget.h" #include "package.h" #include "packagewidget.h" #include "pinwidget.h" #include "portwidget.h" #include "seqlinewidget.h" #include "signalwidget.h" #include "statewidget.h" #include "toolbarstate.h" #include "toolbarstatefactory.h" #include "uml.h" #include "umldoc.h" #include "umldragdata.h" #include "umlfiledialog.h" #include "umllistview.h" #include "umllistviewitem.h" #include "umlobject.h" #include "umlobjectlist.h" #include "umlrole.h" #include "umlscenepopupmenu.h" #include "umlview.h" #include "umlviewimageexporter.h" #include "umlwidget.h" #include "uniqueid.h" #include "widget_factory.h" #include "widget_utils.h" #include "widgetlist_utils.h" //kde include files #if QT_VERSION < 0x050000 #include #include #endif #include #include #include // include files for Qt #include #include #include #include #include #include // system includes #include // for ceil // static members const qreal UMLScene::defaultCanvasSize = 5000; bool UMLScene::m_showDocumentationIndicator = false; using namespace Uml; DEBUG_REGISTER(UMLScene) /** * The class UMLScenePrivate is intended to hold private * members/classes to reduce the size of the public class * and to speed up recompiling. * The migration to this class is not complete yet. */ class UMLScenePrivate { public: UMLScenePrivate(UMLScene *parent) : p(parent) { } /** * Check if there is a corresponding port widget * for all UMLPort instances and add if not. */ void addMissingPorts() { UMLWidgetList ports; UMLWidgetList components; foreach(UMLWidget *w, p->widgetList()) { if (w->isPortWidget()) ports.append(w); else if (w->isComponentWidget()) components.append(w); } foreach(UMLWidget *cw, components) { UMLComponent *c = cw->umlObject()->asUMLComponent(); if (!c) continue; // iterate through related ports for this component widget foreach(UMLObject *o, c->containedObjects()) { UMLPort *up = o->asUMLPort(); if (!up) continue; Uml::ID::Type id = o->id(); bool found = false; foreach(UMLWidget *p, ports) { if (p->id() == id) { found = true; break; } } if (!found) new PortWidget(p, up, cw); } } } /** * Check if port are located equally on the border of a component * and fix position if not. */ void fixPortPositions() { foreach(UMLWidget *w, p->widgetList()) { if (w->isPortWidget()) { QGraphicsItem *g = w->parentItem(); ComponentWidget *c = dynamic_cast(g); Q_ASSERT(c); qreal w2 = w->width()/2; qreal h2 = w->height()/2; if (w->x() <= -w2 || w->y() <= -h2 || w->x() >= c->width() - w2 || w->y() >= c->height() - h2) continue; if (w->x() >= c->width() - 3 * w2) { // right w->setX(c->width() - w2); } else if (w->y() >= c->height() - 3 * h2) { // bottom w->setY(c->height() - h2); } else if (w->x() < 3 * w2) { // left w->setX(-w2); } else if (w->y() < 3 * h2) { // top w->setY(-h2); } else uWarning() << "uncatched widget position of" << w->name(); } } } /** * Check if duplicated floating text labels are in the scene and remove them */ void removeDuplicatedFloatingTextInstances() { UMLWidgetList labelsWithoutParents; UMLWidgetList labelsWithParent; uDebug() << "checking diagram" << p->name() << "id" << Uml::ID::toString(p->ID()); foreach(UMLWidget *w, p->widgetList()) { if (!w->isTextWidget()) continue; if (w->parentItem()) labelsWithParent.append(w); else labelsWithoutParents.append(w); } foreach(UMLWidget *w, labelsWithoutParents) { foreach(UMLWidget *wp, labelsWithParent) { if (w->id() == wp->id() && w->localID() == wp->localID() && w->name() == wp->name()) { p->removeWidgetCmd(w); uDebug() << "removed duplicated text label" << w->name() << "id:" << Uml::ID::toString(w->id()); break; } } } } UMLScene *p; }; /** * Constructor. */ UMLScene::UMLScene(UMLFolder *parentFolder, UMLView *view) : QGraphicsScene(0, 0, defaultCanvasSize, defaultCanvasSize), m_nLocalID(Uml::ID::None), m_nID(Uml::ID::None), m_Type(Uml::DiagramType::Undefined), m_Name(QString()), m_Documentation(QString()), m_Options(Settings::optionState()), m_bUseSnapToGrid(false), m_bUseSnapComponentSizeToGrid(false), m_isOpen(true), m_nCollaborationId(0), m_bCreateObject(false), m_bDrawSelectedOnly(false), m_bPaste(false), m_bStartedCut(false), m_d(new UMLScenePrivate(this)), m_view(view), m_pFolder(parentFolder), m_pIDChangesLog(0), m_isActivated(false), m_bPopupShowing(false), m_autoIncrementSequence(false) { m_PastePoint = QPointF(0, 0); m_pImageExporter = new UMLViewImageExporter(this); // setup signals connect(UMLApp::app(), SIGNAL(sigCutSuccessful()), this, SLOT(slotCutSuccessful())); // Create the ToolBarState factory. This class is not a singleton, because it // needs a pointer to this object. m_pToolBarStateFactory = new ToolBarStateFactory(); m_pToolBarState = m_pToolBarStateFactory->getState(WorkToolBar::tbb_Arrow, this); m_doc = UMLApp::app()->document(); // // settings for background // setBackgroundBrush(QColor(195, 195, 195)); m_layoutGrid = new LayoutGrid(this); // fix crash caused by Qt stale item issue see https://bugs.kde.org/show_bug.cgi?id=383592 setItemIndexMethod(NoIndex); } /** * Destructor. */ UMLScene::~UMLScene() { delete m_pImageExporter; m_pImageExporter = 0; delete m_pIDChangesLog; m_pIDChangesLog = 0; // before we can delete the QCanvas, all widgets must be explicitly // removed // otherwise the implicit remove of the contained widgets will cause // events which would demand a valid connected QCanvas // ==> this causes umbrello to crash for some - larger?? - projects // first avoid all events, which would cause some update actions // on deletion of each removed widget blockSignals(true); removeAllWidgets(); delete m_pToolBarStateFactory; m_pToolBarStateFactory = 0; delete m_layoutGrid; delete m_d; } /** * Return the UMLFolder in which this diagram lives. */ UMLFolder* UMLScene::folder() const { return m_pFolder; } /** * Set the UMLFolder in which this diagram lives. */ void UMLScene::setFolder(UMLFolder *folder) { m_pFolder = folder; } /** * Returns the active view associated with this scene. */ UMLView* UMLScene::activeView() const { return m_view; } /** * Return the documentation of the diagram. */ QString UMLScene::documentation() const { return m_Documentation; } /** * Set the documentation of the diagram. */ void UMLScene::setDocumentation(const QString &doc) { m_Documentation = doc; } /** * Return the state of the auto increment sequence */ bool UMLScene::autoIncrementSequence() const { return m_autoIncrementSequence; } void UMLScene::setAutoIncrementSequence(bool state) { m_autoIncrementSequence = state; } /** * Return the next auto increment sequence value */ QString UMLScene::autoIncrementSequenceValue() { int sequenceNumber = 0; if (type() == Uml::DiagramType::Sequence) { foreach (MessageWidget* message, messageList()) { bool ok; int value = message->sequenceNumber().toInt(&ok); if (ok && value > sequenceNumber) sequenceNumber = value; } } else if (type() == Uml::DiagramType::Collaboration) { foreach (AssociationWidget* assoc, associationList()) { bool ok; int value = assoc->sequenceNumber().toInt(&ok); if (ok && value > sequenceNumber) sequenceNumber = value; } } return QString::number(sequenceNumber + 1); } /** * Return the name of the diagram. */ QString UMLScene::name() const { return m_Name; } /** * Set the name of the diagram. */ void UMLScene::setName(const QString &name) { m_Name = name; } /** * Returns the type of the diagram. */ DiagramType::Enum UMLScene::type() const { return m_Type; } /** * Set the type of diagram. */ void UMLScene::setType(DiagramType::Enum type) { m_Type = type; } /** * Returns the ID of the diagram. */ Uml::ID::Type UMLScene::ID() const { return m_nID; } /** * Sets the ID of the diagram. */ void UMLScene::setID(Uml::ID::Type id) { m_nID = id; } /** * Returns the position of the diagram. */ QPointF UMLScene::pos() const { return m_Pos; } /** * Sets the position of the diagram. */ void UMLScene::setPos(const QPointF &pos) { m_Pos = pos; } /** * Returns the fill color to use. */ const QColor& UMLScene::fillColor() const { return m_Options.uiState.fillColor; } /** * Set the background color. * * @param color The color to use. */ void UMLScene::setFillColor(const QColor &color) { m_Options.uiState.fillColor = color; emit sigFillColorChanged(ID()); } /** * Returns the line color to use. */ const QColor& UMLScene::lineColor() const { return m_Options.uiState.lineColor; } /** * Sets the line color. * * @param color The color to use. */ void UMLScene::setLineColor(const QColor &color) { m_Options.uiState.lineColor = color; emit sigLineColorChanged(ID()); } /** * Returns the line width to use. */ uint UMLScene::lineWidth() const { return m_Options.uiState.lineWidth; } /** * Sets the line width. * * @param width The width to use. */ void UMLScene::setLineWidth(uint width) { m_Options.uiState.lineWidth = width; emit sigLineWidthChanged(ID()); } /** * Returns the text color to use. */ const QColor& UMLScene::textColor() const { return m_Options.uiState.textColor; } /** * Sets the text color. * * @param color The color to use. */ void UMLScene::setTextColor(const QColor& color) { m_Options.uiState.textColor = color; emit sigTextColorChanged(ID()); } /** * return grid dot color * * @return Color */ const QColor& UMLScene::gridDotColor() const { return m_layoutGrid->gridDotColor(); } /** * set grid dot color * * @param color grid dot color */ void UMLScene::setGridDotColor(const QColor& color) { m_Options.uiState.gridDotColor = color; m_layoutGrid->setGridDotColor(color); } /** * Returns the options being used. */ Settings::OptionState& UMLScene::optionState() { return m_Options; } /** * Sets the options to be used. */ void UMLScene::setOptionState(const Settings::OptionState& options) { m_Options = options; setBackgroundBrush(options.uiState.backgroundColor); setGridDotColor(options.uiState.gridDotColor); } /** * Returns a reference to the association list. */ const AssociationWidgetList UMLScene::associationList() const { AssociationWidgetList result; foreach(QGraphicsItem *item, items()) { AssociationWidget *w = dynamic_cast(item); if (w) result.append(w); } return result; } /** * Returns a reference to the widget list. */ const UMLWidgetList UMLScene::widgetList() const { UMLWidgetList result; foreach(QGraphicsItem *item, items()) { UMLWidget *w = dynamic_cast(item); if (w && !w->isMessageWidget() && !w->isAssociationWidget()) result.append(w); } return result; } void UMLScene::addWidgetCmd(UMLWidget* widget) { Q_ASSERT(0 != widget); addItem(widget); } void UMLScene::addWidgetCmd(AssociationWidget* widget) { Q_ASSERT(0 != widget); addItem(widget); } /** * Returns a reference to the message list. */ const MessageWidgetList UMLScene::messageList() const { MessageWidgetList result; foreach(QGraphicsItem *item, items()) { MessageWidget *w = dynamic_cast(item); if (w) result.append(w); } return result; } /** * Used for creating unique name of collaboration messages. */ int UMLScene::generateCollaborationId() { return ++m_nCollaborationId; } /** * Returns the open state. * @return when true diagram is shown to the user */ bool UMLScene::isOpen() const { return m_isOpen; } /** * Sets the flag 'isOpen'. * @param isOpen flag indicating that the diagram is shown to the user */ void UMLScene::setIsOpen(bool isOpen) { m_isOpen = isOpen; } /** * Contains the implementation for printing functionality. */ void UMLScene::print(QPrinter *pPrinter, QPainter & pPainter) { bool isFooter = optionState().generalState.footerPrinting; // The printer will probably use a different font with different font metrics, // force the widgets to update accordingly on paint forceUpdateWidgetFontMetrics(&pPainter); QRectF source = diagramRect(); QRect paper = pPrinter->paperRect(); QRect page = pPrinter->pageRect(); // use the painter font metrics, not the screen fm! QFontMetrics fm = pPainter.fontMetrics(); int fontHeight = fm.lineSpacing(); if (paper == page) { QSize margin = page.size() * 0.025; page.adjust(margin.width(), margin.height(), -margin.width(), -margin.height()); } if (isFooter) { int margin = 3 + 3 * fontHeight; page.adjust(0, 0, 0, -margin); } getDiagram(pPainter, QRectF(source), QRectF(page)); //draw foot note if (isFooter) { page.adjust(0, 0, 0, fontHeight); QString string = i18n("Diagram: %2 Page %1", 1, name()); QColor textColor(50, 50, 50); pPainter.setPen(textColor); pPainter.drawLine(page.left(), page.bottom() , page.right(), page.bottom()); pPainter.drawText(page.left(), page.bottom() + 3, page.right(), 2*fontHeight, Qt::AlignLeft, string); } // next painting will most probably be to a different device (i.e. the screen) forceUpdateWidgetFontMetrics(0); } /** * Initialize and announce a newly created widget. * Auxiliary to contentsMouseReleaseEvent(). */ void UMLScene::setupNewWidget(UMLWidget *w, bool setPosition) { if (setPosition && (!w->isPinWidget()) && (!w->isPortWidget()) && (!w->isObjectWidget())) { // ObjectWidget's position is handled by the widget w->setX(m_Pos.x()); w->setY(m_Pos.y()); } w->setVisible(true); w->activate(); w->setFontCmd(font()); w->slotFillColorChanged(ID()); w->slotTextColorChanged(ID()); w->slotLineWidthChanged(ID()); resizeSceneToItems(); m_doc->setModified(); if (m_doc->loading()) { // do not emit signals while loading addWidgetCmd(w); // w->activate(); // will be done by UMLDoc::activateAllViews() after loading } else { UMLApp::app()->executeCommand(new CmdCreateWidget(w)); } } /** * Return whether we are currently creating an object. */ bool UMLScene::getCreateObject() const { return m_bCreateObject; } /** * Set whether we are currently creating an object. */ void UMLScene::setCreateObject(bool bCreate) { m_bCreateObject = bCreate; } /** * Overrides the standard operation. */ void UMLScene::showEvent(QShowEvent* /*se*/) { connect(m_doc, SIGNAL(sigObjectCreated(UMLObject*)), this, SLOT(slotObjectCreated(UMLObject*))); connect(this, SIGNAL(sigAssociationRemoved(AssociationWidget*)), UMLApp::app()->docWindow(), SLOT(slotAssociationRemoved(AssociationWidget*))); connect(this, SIGNAL(sigWidgetRemoved(UMLWidget*)), UMLApp::app()->docWindow(), SLOT(slotWidgetRemoved(UMLWidget*))); } /** * Overrides the standard operation. */ void UMLScene::hideEvent(QHideEvent* /*he*/) { disconnect(m_doc, SIGNAL(sigObjectCreated(UMLObject*)), this, SLOT(slotObjectCreated(UMLObject*))); disconnect(this, SIGNAL(sigAssociationRemoved(AssociationWidget*)), UMLApp::app()->docWindow(), SLOT(slotAssociationRemoved(AssociationWidget*))); disconnect(this, SIGNAL(sigWidgetRemoved(UMLWidget*)), UMLApp::app()->docWindow(), SLOT(slotWidgetRemoved(UMLWidget*))); } /** * Changes the current tool to the selected tool. * The current tool is cleaned and the selected tool initialized. */ void UMLScene::slotToolBarChanged(int c) { m_pToolBarState->cleanBeforeChange(); m_pToolBarState = m_pToolBarStateFactory->getState((WorkToolBar::ToolBar_Buttons)c, this); m_pToolBarState->init(); m_bPaste = false; } /** * Slot called when an object is created. * @param o created UML object */ void UMLScene::slotObjectCreated(UMLObject* o) { DEBUG(DBG_SRC) << "scene=" << name() << " / object=" << o->name(); m_bPaste = false; //check to see if we want the message //may be wanted by someone else e.g. list view if (!m_bCreateObject) { return; } UMLWidget* newWidget = Widget_Factory::createWidget(this, o); if (!newWidget) { return; } setupNewWidget(newWidget); m_bCreateObject = false; if (Model_Utils::hasAssociations(o->baseType())) { createAutoAssociations(newWidget); // We need to invoke createAutoAttributeAssociations() // on all other widgets again because the newly created // widget might saturate some latent attribute assocs. createAutoAttributeAssociations2(newWidget); } resizeSceneToItems(); } /** * Slot called when an object is removed. * @param o removed UML object */ void UMLScene::slotObjectRemoved(UMLObject * o) { m_bPaste = false; Uml::ID::Type id = o->id(); foreach(UMLWidget* obj, widgetList()) { if (obj->id() != id) continue; removeWidget(obj); break; } } /** * Override standard method. */ void UMLScene::dragEnterEvent(QGraphicsSceneDragDropEvent *e) { UMLDragData::LvTypeAndID_List tidList; if (!UMLDragData::getClip3TypeAndID(e->mimeData(), tidList)) { DEBUG(DBG_SRC) << "UMLDragData::getClip3TypeAndID returned false"; return; } for(UMLDragData::LvTypeAndID_List::const_iterator it = tidList.begin(); it != tidList.end(); it++) { UMLListViewItem::ListViewType lvtype = (*it)->type; Uml::ID::Type id = (*it)->id; DiagramType::Enum diagramType = type(); UMLObject* temp = 0; //if dragging diagram - might be a drag-to-note if (Model_Utils::typeIsDiagram(lvtype)) { e->accept(); continue; } //can't drag anything onto state/activity diagrams if (diagramType == DiagramType::State || diagramType == DiagramType::Activity) { e->ignore(); continue; } //make sure can find UMLObject if (!(temp = m_doc->findObjectById(id))) { DEBUG(DBG_SRC) << "object " << Uml::ID::toString(id) << " not found"; e->ignore(); continue; } bool bAccept = Model_Utils::typeIsAllowedInDiagram(temp, this); if (bAccept) { e->accept(); } else { e->ignore(); } } } /** * Override standard method. */ void UMLScene::dragMoveEvent(QGraphicsSceneDragDropEvent* e) { e->accept(); } /** * Override standard method. */ void UMLScene::dropEvent(QGraphicsSceneDragDropEvent *e) { UMLDragData::LvTypeAndID_List tidList; if (!UMLDragData::getClip3TypeAndID(e->mimeData(), tidList)) { DEBUG(DBG_SRC) << "UMLDragData::getClip3TypeAndID returned error"; return; } m_Pos = e->scenePos(); for(UMLDragData::LvTypeAndID_List::const_iterator it = tidList.begin(); it != tidList.end(); it++) { UMLListViewItem::ListViewType lvtype = (*it)->type; Uml::ID::Type id = (*it)->id; if (Model_Utils::typeIsDiagram(lvtype)) { bool breakFlag = false; UMLWidget* w = 0; foreach(w, widgetList()) { if (w->isNoteWidget() && w->onWidget(e->scenePos())) { breakFlag = true; break; } } if (breakFlag) { NoteWidget *note = static_cast(w); note->setDiagramLink(id); } continue; } UMLObject* o = m_doc->findObjectById(id); if (!o) { DEBUG(DBG_SRC) << "object id=" << Uml::ID::toString(id) << " not found"; continue; } UMLWidget* newWidget = Widget_Factory::createWidget(this, o); if (!newWidget) { uWarning() << "could not create widget for uml object" << o->name(); continue; } setupNewWidget(newWidget); m_Pos += QPointF(UMLWidget::DefaultMinimumSize.width(), UMLWidget::DefaultMinimumSize.height()); createAutoAssociations(newWidget); createAutoAttributeAssociations2(newWidget); } } /** * Overrides the standard operation. * Calls the same method in the current tool bar state. */ void UMLScene::mouseMoveEvent(QGraphicsSceneMouseEvent* ome) { m_pToolBarState->mouseMove(ome); } /** * Override standard method. * Calls the same method in the current tool bar state. */ void UMLScene::mousePressEvent(QGraphicsSceneMouseEvent* event) { if (event->button() != Qt::LeftButton) { event->ignore(); return; } m_pToolBarState->mousePress(event); //TODO should be managed by widgets when are selected. Right now also has some //problems, such as clicking on a widget, and clicking to move that widget shows //documentation of the diagram instead of keeping the widget documentation. //When should diagram documentation be shown? When clicking on an empty //space in the diagram with arrow tool? UMLWidget* widget = widgetAt(event->scenePos()); if (widget) { DEBUG(DBG_SRC) << "widget = " << widget->name() << " / type = " << widget->baseTypeStr(); UMLApp::app()->docWindow()->showDocumentation(widget); event->accept(); } else { AssociationWidget* association = associationAt(event->scenePos()); if (association) { DEBUG(DBG_SRC) << "association widget = " << association->name() << " / type = " << association->baseTypeStr(); // the following is done in AssociationWidget::setSelected() // UMLApp::app()->docWindow()->showDocumentation(association, true); // event->accept(); } //:TODO: else if (clicking on other elements with documentation) { //:TODO: UMLApp::app()->docWindow()->showDocumentation(umlObject, true); else { // clicking on an empty space in the diagram with arrow tool UMLApp::app()->docWindow()->showDocumentation(this); event->accept(); } } } /** * Override standard method. * Calls the same method in the current tool bar state. */ void UMLScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) { if (!m_doc->loading()) m_pToolBarState->mouseDoubleClick(event); if (!event->isAccepted()) { // show properties dialog of the scene if (m_view->showPropertiesDialog() == true) { m_doc->setModified(); } event->accept(); } } /** * Overrides the standard operation. * Calls the same method in the current tool bar state. */ void UMLScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* ome) { m_pToolBarState->mouseRelease(ome); } /** * Determine whether on a sequence diagram we have clicked on a line * of an Object. * * @return The widget owning the line which was clicked. * Returns 0 if no line was clicked on. */ ObjectWidget * UMLScene::onWidgetLine(const QPointF &point) const { foreach(UMLWidget* obj, widgetList()) { ObjectWidget *ow = obj->asObjectWidget(); if (ow == 0) continue; SeqLineWidget *pLine = ow->sequentialLine(); if (pLine == 0) { uError() << "SeqLineWidget of " << ow->name() << " (id=" << Uml::ID::toString(ow->localID()) << ") is NULL"; continue; } if (pLine->onWidget(point)) return ow; } return 0; } /** * Determine whether on a sequence diagram we have clicked on * the destruction box of an Object. * * @return The widget owning the destruction box which was clicked. * Returns 0 if no destruction box was clicked on. */ ObjectWidget * UMLScene::onWidgetDestructionBox(const QPointF &point) const { foreach(UMLWidget* obj, widgetList()) { ObjectWidget *ow = obj->asObjectWidget(); if (ow == 0) continue; SeqLineWidget *pLine = ow->sequentialLine(); if (pLine == 0) { uError() << "SeqLineWidget of " << ow->name() << " (id=" << Uml::ID::toString(ow->localID()) << ") is NULL"; continue; } if (pLine->onDestructionBox(point)) return ow; } return 0; } /** * Return pointer to the first selected widget (for multi-selection) */ UMLWidget* UMLScene::getFirstMultiSelectedWidget() const { if (selectedWidgets().size() == 0) return 0; return selectedWidgets().first(); } /** * Tests the given point against all widgets and returns the * widget for which the point is within its bounding rectangle. * In case of multiple matches, returns the smallest widget. * Returns NULL if the point is not inside any widget. * TODO: What about using QGraphicsScene::items(...)? */ UMLWidget* UMLScene::widgetAt(const QPointF& p) { return dynamic_cast(itemAt(p)); } /** * Tests the given point against all associations and returns the * association widget for which the point is on the line. * Returns NULL if the point is not inside any association. * CHECK: This is the same method as in ToolBarState. */ AssociationWidget* UMLScene::associationAt(const QPointF& p) { foreach (AssociationWidget* association, associationList()) { if (association->onAssociation(p)) { return association; } } return 0; } /** * Tests the given point against all associations and returns the * association widget for which the point is on the line. * Returns NULL if the point is not inside any association. */ MessageWidget* UMLScene::messageAt(const QPointF& p) { foreach(MessageWidget *message, messageList()) { if (message->onWidget(p)) { return message; } } return 0; } /** * Sees if a message is relevant to the given widget. If it does delete it. * @param w The widget to check messages against. */ void UMLScene::checkMessages(ObjectWidget * w) { if (type() != DiagramType::Sequence) { return; } foreach(MessageWidget *obj, messageList()) { if (obj->hasObjectWidget(w)) { removeWidgetCmd(obj); } } } /** * Returns whether a widget is already on the diagram. * * @param id The id of the widget to check for. * * @return Returns pointer to the widget if it is on the diagram, NULL if not. */ UMLWidget* UMLScene::widgetOnDiagram(Uml::ID::Type id) { foreach(UMLWidget *obj, widgetList()) { if (!obj) continue; UMLWidget* w = obj->widgetWithID(id); if (w) return w; } foreach(UMLWidget *obj, messageList()) { // CHECK: Should MessageWidget reimplement widgetWithID() ? // If yes then we should use obj->widgetWithID(id) here too. if (id == obj->id()) return obj; } return 0; } /** * Finds a widget with the given ID. * Search both our UMLWidget AND MessageWidget lists. * @param id The ID of the widget to find. * * @return Returns the widget found, returns 0 if no widget found. */ UMLWidget * UMLScene::findWidget(Uml::ID::Type id) { foreach(UMLWidget* obj, widgetList()) { if (!obj) continue; UMLWidget* w = obj->widgetWithID(id); if (w) { return w; } } foreach(UMLWidget* obj, messageList()) { // CHECK: Should MessageWidget reimplement widgetWithID() ? // If yes then we should use obj->widgetWithID(id) here too. if (obj->localID() == id || obj->id() == id) return obj; } return 0; } /** * Finds an association widget with the given ID. * * @param id The ID of the widget to find. * * @return Returns the widget found, returns 0 if no widget found. */ AssociationWidget * UMLScene::findAssocWidget(Uml::ID::Type id) { foreach(AssociationWidget* obj, associationList()) { UMLAssociation* umlassoc = obj->association(); if (umlassoc && umlassoc->id() == id) { return obj; } } return 0; } /** * Finds an association widget with the given widgets and the given role B name. * Considers the following association types: * at_Association, at_UniAssociation, at_Composition, at_Aggregation * This is used for seeking an attribute association. * * @param pWidgetA Pointer to the UMLWidget of role A. * @param pWidgetB Pointer to the UMLWidget of role B. * @param roleNameB Name at the B side of the association (the attribute name) * * @return Returns the widget found, returns 0 if no widget found. */ AssociationWidget * UMLScene::findAssocWidget(UMLWidget *pWidgetA, UMLWidget *pWidgetB, const QString& roleNameB) { foreach(AssociationWidget* assoc, associationList()) { const Uml::AssociationType::Enum testType = assoc->associationType(); if (testType != Uml::AssociationType::Association && testType != Uml::AssociationType::UniAssociation && testType != Uml::AssociationType::Composition && testType != Uml::AssociationType::Aggregation && testType != Uml::AssociationType::Relationship) { continue; } if (pWidgetA->id() == assoc->widgetIDForRole(Uml::RoleType::A) && pWidgetB->id() == assoc->widgetIDForRole(Uml::RoleType::B) && assoc->roleName(Uml::RoleType::B) == roleNameB) { return assoc; } } return 0; } /** * Finds an association widget with the given type and widgets. * * @param at The AssociationType of the widget to find. * @param pWidgetA Pointer to the UMLWidget of role A. * @param pWidgetB Pointer to the UMLWidget of role B. * * @return Returns the widget found, returns 0 if no widget found. */ AssociationWidget * UMLScene::findAssocWidget(AssociationType::Enum at, UMLWidget *pWidgetA, UMLWidget *pWidgetB) { foreach(AssociationWidget* assoc, associationList()) { Uml::AssociationType::Enum testType = assoc->associationType(); if (testType != at) { continue; } if (pWidgetA->id() == assoc->widgetIDForRole(Uml::RoleType::A) && pWidgetB->id() == assoc->widgetIDForRole(Uml::RoleType::B)) { return assoc; } } return 0; } /** * Remove a widget from view (undo command) * * @param o The widget to remove. */ void UMLScene::removeWidget(UMLWidget * o) { UMLApp::app()->executeCommand(new CmdRemoveWidget(o)); } /** * Remove a widget from view. * * @param o The widget to remove. */ void UMLScene::removeWidgetCmd(UMLWidget * o) { if (!o) return; emit sigWidgetRemoved(o); removeAssociations(o); removeOwnedWidgets(o); WidgetBase::WidgetType t = o->baseType(); if (type() == DiagramType::Sequence && t == WidgetBase::wt_Object) { checkMessages(static_cast(o)); } o->cleanup(); o->setSelectedFlag(false); disconnect(this, SIGNAL(sigFillColorChanged(Uml::ID::Type)), o, SLOT(slotFillColorChanged(Uml::ID::Type))); disconnect(this, SIGNAL(sigLineColorChanged(Uml::ID::Type)), o, SLOT(slotLineColorChanged(Uml::ID::Type))); disconnect(this, SIGNAL(sigTextColorChanged(Uml::ID::Type)), o, SLOT(slotTextColorChanged(Uml::ID::Type))); removeItem(o); o->deleteLater(); m_doc->setModified(true); } /** * Remove all widgets that have given widget as owner. * * @param o The owner widget that will be removed. */ void UMLScene::removeOwnedWidgets(UMLWidget* o) { foreach(QGraphicsItem* item, o->childItems()) { UMLWidget* widget = dynamic_cast(item); if ((widget != 0) && (widget->isPinWidget() || widget->isPortWidget())) { removeWidgetCmd(widget); } } } /** * Returns background color */ const QColor& UMLScene::backgroundColor() const { return backgroundBrush().color(); } /** * Returns whether to use the fill/background color */ bool UMLScene::useFillColor() const { return m_Options.uiState.useFillColor; } /** * Sets whether to use the fill/background color */ void UMLScene::setUseFillColor(bool ufc) { m_Options.uiState.useFillColor = ufc; } /** * Gets the smallest area to print. * * @return Returns the smallest area to print. */ QRectF UMLScene::diagramRect() { return itemsBoundingRect(); } /** * Returns a list of selected widgets * @return list of selected widgets based on class UMLWidget * @note This method returns widgets including message widgets, but no association widgets */ UMLWidgetList UMLScene::selectedWidgets() const { QList items = selectedItems(); UMLWidgetList widgets; foreach(QGraphicsItem *item, items) { UMLWidget *w = dynamic_cast(item); if (w) widgets.append(w); } return widgets; } /** * Returns a list of selected association widgets * @return list of selected widgets based on class AssociationWidget */ AssociationWidgetList UMLScene::selectedAssociationWidgets() const { QList items = selectedItems(); AssociationWidgetList widgets; foreach(QGraphicsItem *item, items) { AssociationWidget *w = dynamic_cast(item); if (w) widgets.append(w); } return widgets; } /** * Returns a list of selected message widgets * @return list of selected widgets based on class MessageWidget */ UMLWidgetList UMLScene::selectedMessageWidgets() const { QList items = selectedItems(); UMLWidgetList widgets; foreach(QGraphicsItem *item, items) { MessageWidget *w = dynamic_cast(item); if (w) widgets.append(w); } return widgets; } /** * Clear the selected widgets list. */ void UMLScene::clearSelected() { clearSelection(); //m_doc->enableCutCopy(false); } /** * Move all the selected widgets by a relative X and Y offset. * TODO: Only used in UMLApp::handleCursorKeyReleaseEvent * * @param dX The distance to move horizontally. * @param dY The distance to move vertically. */ void UMLScene::moveSelectedBy(qreal dX, qreal dY) { // DEBUG(DBG_SRC) << "********** m_selectedList count=" << m_selectedList.count(); foreach(UMLWidget *w, selectedWidgets()) { w->moveByLocal(dX, dY); } } /** * Set the useFillColor variable to all selected widgets * * @param useFC The state to set the widget to. */ void UMLScene::selectionUseFillColor(bool useFC) { if (useFC) { UMLApp::app()->beginMacro(i18n("Use fill color")); } else { UMLApp::app()->beginMacro(i18n("No fill color")); } foreach(UMLWidget* widget, selectedWidgets()) { widget->setUseFillColor(useFC); } UMLApp::app()->endMacro(); } /** * Set the font for all the currently selected items. */ void UMLScene::selectionSetFont(const QFont &font) { UMLApp::app()->beginMacro(i18n("Change font")); foreach(UMLWidget* temp, selectedWidgets()) { temp->setFont(font); } UMLApp::app()->endMacro(); } /** * Set the line color for all the currently selected items. */ void UMLScene::selectionSetLineColor(const QColor &color) { UMLApp::app()->beginMacro(i18n("Change line color")); foreach(UMLWidget *temp, selectedWidgets()) { temp->setLineColor(color); } AssociationWidgetList assoclist = selectedAssocs(); foreach(AssociationWidget *aw, assoclist) { aw->setLineColor(color); } UMLApp::app()->endMacro(); } /** * Set the line width for all the currently selected items. */ void UMLScene::selectionSetLineWidth(uint width) { UMLApp::app()->beginMacro(i18n("Change line width")); foreach(UMLWidget* temp, selectedWidgets()) { temp->setLineWidth(width); temp->setUsesDiagramLineWidth(false); } AssociationWidgetList assoclist = selectedAssocs(); foreach(AssociationWidget *aw, assoclist) { aw->setLineWidth(width); aw->setUsesDiagramLineWidth(false); } UMLApp::app()->endMacro(); } /** * Set the fill color for all the currently selected items. */ void UMLScene::selectionSetFillColor(const QColor &color) { UMLApp::app()->beginMacro(i18n("Change fill color")); foreach(UMLWidget* widget, selectedWidgets()) { widget->setFillColor(color); widget->setUsesDiagramFillColor(false); } UMLApp::app()->endMacro(); } /** * Set or unset the visual property (show ..) setting of all selected items. */ void UMLScene::selectionSetVisualProperty(ClassifierWidget::VisualProperty property, bool value) { UMLApp::app()->beginMacro(i18n("Change visual property")); foreach(UMLWidget *temp, selectedWidgets()) { ClassifierWidget *cw = temp->asClassifierWidget(); cw->setVisualProperty(property, value); } UMLApp::app()->endMacro(); } /** * Unselect child widgets when their owner is already selected. */ void UMLScene::unselectChildrenOfSelectedWidgets() { foreach(UMLWidget* widget, selectedWidgets()) { if (widget->isPinWidget() || widget->isPortWidget()) { foreach(UMLWidget* potentialParentWidget, selectedWidgets()) { if (widget->parentItem() == potentialParentWidget) { widget->setSelectedFlag(false); } } } } } /** * Delete the selected widgets list and the widgets in it. */ void UMLScene::deleteSelection() { AssociationWidgetList selectedAssociations = selectedAssociationWidgets(); int selectionCount = selectedWidgets().count() + selectedAssociations.count(); if (selectionCount == 0) return; // check related associations bool hasAssociations = false; foreach(UMLWidget* widget, selectedWidgets()) { if (widget->isTextWidget() && widget->asFloatingTextWidget()->textRole() != Uml::TextRole::Floating) { continue; } if (widget->isMessageWidget() || widget->associationWidgetList().size() > 0) hasAssociations = true; } if (hasAssociations && !Dialog_Utils::askDeleteAssociation()) return; UMLApp::app()->beginMacro(i18n("Delete widgets")); unselectChildrenOfSelectedWidgets(); foreach(UMLWidget* widget, selectedWidgets()) { // Don't delete text widget that are connect to associations as these will // be cleaned up by the associations. if (widget->isTextWidget() && widget->asFloatingTextWidget()->textRole() != Uml::TextRole::Floating) { widget->setSelectedFlag(false); widget->hide(); } else if (widget->isPortWidget()) { UMLObject *o = widget->umlObject(); removeWidget(widget); if (o) UMLApp::app()->executeCommand(new CmdRemoveUMLObject(o)); // message widgets are handled later } else if (!widget->isMessageWidget()){ removeWidget(widget); } } // Delete any selected associations. foreach(AssociationWidget* assocwidget, selectedAssociations) { removeWidgetCmd(assocwidget); } // we also have to remove selected messages from sequence diagrams foreach(UMLWidget* cur_msgWgt, selectedMessageWidgets()) { removeWidget(cur_msgWgt); } //make sure list empty - it should be anyway, just a check. clearSelected(); UMLApp::app()->endMacro(); } /** * resize selected widgets */ void UMLScene::resizeSelection() { int selectionCount = selectedWidgets().count(); if (selectionCount > 1) { UMLApp::app()->beginMacro(i18n("Resize widgets")); } if (selectedCount() == 0) return; foreach(UMLWidget *w, selectedWidgets()) { w->resize(); } m_doc->setModified(); if (selectionCount > 1) { UMLApp::app()->endMacro(); } } /** * Selects all widgets */ void UMLScene::selectAll() { selectWidgets(sceneRect().left(), sceneRect().top(), sceneRect().right(), sceneRect().bottom()); } /** * Returns true if this diagram resides in an externalized folder. * CHECK: It is probably cleaner to move this to the UMLListViewItem. */ bool UMLScene::isSavedInSeparateFile() { if (optionState().generalState.tabdiagrams) { // Umbrello currently does not support external folders // when tabbed diagrams are enabled. return false; } const QString msgPrefix(QLatin1String("UMLScene::isSavedInSeparateFile(") + name() + QLatin1String("): ")); UMLListView *listView = UMLApp::app()->listView(); UMLListViewItem *lvItem = listView->findItem(m_nID); if (lvItem == 0) { uError() << msgPrefix << "listView->findUMLObject(this) returns false"; return false; } UMLListViewItem *parentItem = dynamic_cast(lvItem->parent()); if (parentItem == 0) { uError() << msgPrefix << "parent item in listview is not a UMLListViewItem (?)"; return false; } const UMLListViewItem::ListViewType lvt = parentItem->type(); if (! Model_Utils::typeIsFolder(lvt)) return false; UMLFolder *modelFolder = parentItem->umlObject()->asUMLFolder(); if (modelFolder == 0) { uError() << msgPrefix << "parent model object is not a UMLFolder (?)"; return false; } QString folderFile = modelFolder->folderFile(); return !folderFile.isEmpty(); } UMLSceneItemList UMLScene::collisions(const QPointF &p, int delta) { QPointF a = p-QPointF(delta, delta); QPointF b = p+QPointF(delta, delta); QList list = items(QRectF(a, b)); return list; } /** * Calls setSelected on the given UMLWidget and enters * it into the m_selectedList while making sure it is * there only once. */ void UMLScene::makeSelected(UMLWidget* uw) { if (uw) { uw->setSelected(true); } } /** * Selects all the widgets of the given association widget. */ void UMLScene::selectWidgetsOfAssoc(AssociationWidget * a) { if (a) { a->setSelected(true); //select the two widgets makeSelected(a->widgetForRole(Uml::RoleType::A)); makeSelected(a->widgetForRole(Uml::RoleType::B)); //select all the text makeSelected(a->multiplicityWidget(Uml::RoleType::A)); makeSelected(a->multiplicityWidget(Uml::RoleType::B)); makeSelected(a->roleWidget(Uml::RoleType::A)); makeSelected(a->roleWidget(Uml::RoleType::B)); makeSelected(a->changeabilityWidget(Uml::RoleType::A)); makeSelected(a->changeabilityWidget(Uml::RoleType::B)); } } /** * Selects all the widgets within an internally kept rectangle. */ void UMLScene::selectWidgets(qreal px, qreal py, qreal qx, qreal qy) { clearSelected(); QRectF rect; if (px <= qx) { rect.setLeft(px); rect.setRight(qx); } else { rect.setLeft(qx); rect.setRight(px); } if (py <= qy) { rect.setTop(py); rect.setBottom(qy); } else { rect.setTop(qy); rect.setBottom(py); } // Select UMLWidgets that fall within the selection rectangle foreach(UMLWidget* temp, widgetList()) { uIgnoreZeroPointer(temp); selectWidget(temp, &rect); } // Select messages that fall within the selection rectangle foreach(MessageWidget* temp, messageList()) { selectWidget(temp->asUMLWidget(), &rect); } // Select associations of selected widgets selectAssociations(true); // Automatically select all messages if two object widgets are selected foreach(MessageWidget *w, messageList()) { if (w->objectWidget(Uml::RoleType::A) && w->objectWidget(Uml::RoleType::B) && w->objectWidget(Uml::RoleType::A)->isSelected() && w->objectWidget(Uml::RoleType::B)->isSelected()) { makeSelected(w); } } } /** * Select a single widget * * If QRectF* rect is provided, the selection is only made if the widget is * visible within the rectangle. */ void UMLScene::selectWidget(UMLWidget* widget, QRectF* rect) { if (rect == 0) { makeSelected(widget); return; } int x = widget->x(); int y = widget->y(); int w = widget->width(); int h = widget->height(); QRectF rect2(x, y, w, h); //see if any part of widget is in the rectangle if (!rect->intersects(rect2)) { return; } //if it is text that is part of an association then select the association //and the objects that are connected to it. if (widget->isTextWidget()) { FloatingTextWidget *ft = widget->asFloatingTextWidget(); Uml::TextRole::Enum t = ft->textRole(); LinkWidget *lw = ft->link(); MessageWidget * mw = dynamic_cast(lw); if (mw) { makeSelected(mw); } else if (t != Uml::TextRole::Floating) { AssociationWidget * a = dynamic_cast(lw); if (a) selectWidgetsOfAssoc(a); } } else if (widget->isMessageWidget()) { MessageWidget *mw = widget->asMessageWidget(); makeSelected(mw); } if (widget->isVisible()) { makeSelected(widget); } } /** * Selects all the widgets from a list. */ void UMLScene::selectWidgets(UMLWidgetList &widgets) { foreach (UMLWidget* widget, widgets) makeSelected(widget); } /** * Returns the PNG picture of the paste operation. * @param diagram the class to store PNG picture of the paste operation. * @param rect the area of the diagram to copy */ void UMLScene::getDiagram(QPixmap &diagram, const QRectF &rect) { DEBUG(DBG_SRC) << "rect=" << rect << ", pixmap=" << diagram.rect(); QPainter painter(&diagram); painter.fillRect(0, 0, rect.width(), rect.height(), Qt::white); getDiagram(painter, rect); } /** * Paint diagram to the paint device * @param painter the QPainter to which the diagram is painted * @param source the area of the diagram to copy * @param target the rect where to paint into */ void UMLScene::getDiagram(QPainter &painter, const QRectF &source, const QRectF &target) { DEBUG(DBG_SRC) << "painter=" << painter.window() << ", source=" << source << ", target=" << target; //TODO unselecting and selecting later doesn't work now as the selection is //cleared in UMLSceneImageExporter. Check if the anything else than the //following is needed and, if it works, remove the clearSelected in //UMLSceneImageExporter and UMLSceneImageExporterModel UMLWidgetList selected = selectedWidgets(); foreach(UMLWidget* widget, selected) { widget->setSelected(false); } AssociationWidgetList selectedAssociationsList = selectedAssocs(); foreach(AssociationWidget* association, selectedAssociationsList) { association->setSelected(false); } // we don't want to get the grid bool showSnapGrid = isSnapGridVisible(); setSnapGridVisible(false); const int sourceMargin = 1; QRectF alignedSource(source); alignedSource.adjust(-sourceMargin, -sourceMargin, sourceMargin, sourceMargin); uDebug() << "TODO: Check if this render method is identical to cavnas()->drawArea()"; // [PORT] render(&painter, target, alignedSource, Qt::KeepAspectRatio); setSnapGridVisible(showSnapGrid); //select again foreach(UMLWidget* widget, selected) { widget->setSelected(true); } foreach(AssociationWidget* association, selectedAssociationsList) { association->setSelected(true); } } /** * Returns the imageExporter used to export the view. * * @return The imageExporter used to export the view. */ UMLViewImageExporter* UMLScene::getImageExporter() { return m_pImageExporter; } /** * makes this view the active view by asking the document to show us */ void UMLScene::slotActivate() { m_doc->changeCurrentView(ID()); } /** * Activate all the objects and associations after a load from the clipboard */ void UMLScene::activate() { //Activate Regular widgets then activate messages foreach(UMLWidget* obj, widgetList()) { uIgnoreZeroPointer(obj); //If this UMLWidget is already activated or is a MessageWidget then skip it if (obj->isActivated() || obj->isMessageWidget()) { continue; } if (obj->activate()) { obj->setVisible(true); } else { removeItem(obj); delete obj; } }//end foreach //Activate Message widgets foreach(UMLWidget* obj, messageList()) { //If this MessageWidget is already activated then skip it if (obj->isActivated()) continue; obj->activate(m_doc->changeLog()); obj->setVisible(true); }//end foreach // Activate all association widgets foreach(AssociationWidget* aw, associationList()) { if (aw->activate()) { if (m_PastePoint.x() != 0) { int x = m_PastePoint.x() - m_Pos.x(); int y = m_PastePoint.y() - m_Pos.y(); aw->moveEntireAssoc(x, y); } } else { removeWidgetCmd(aw); delete aw; } } } /** * Return the amount of widgets selected. * * @param filterText When true, do NOT count floating text widgets that * belong to other widgets (i.e. only count TextRole::Floating.) * Default: Count all widgets. * @return Number of widgets selected. */ int UMLScene::selectedCount(bool filterText) const { if (!filterText) return selectedWidgets().count(); int counter = 0; foreach(UMLWidget* temp, selectedWidgets()) { if (temp->isTextWidget()) { const FloatingTextWidget *ft = static_cast(temp); if (ft->textRole() == TextRole::Floating) counter++; } else { counter++; } } return counter; } /** * Fills the List with all the selected widgets from the diagram * The list can be filled with all the selected widgets, or be filtered to prevent * text widgets other than tr_Floating to be append. * * @param filterText Don't append the text, unless their role is tr_Floating * @return The UMLWidgetList to fill. */ UMLWidgetList UMLScene::selectedWidgetsExt(bool filterText /*= true*/) { UMLWidgetList widgetList; foreach(UMLWidget* widgt, selectedWidgets()) { if (filterText && widgt->isTextWidget()) { FloatingTextWidget *ft = widgt->asFloatingTextWidget(); if (ft->textRole() == Uml::TextRole::Floating) widgetList.append(widgt); } else { widgetList.append(widgt); } } return widgetList; } /** * Returns a list with all the selected associations from the diagram */ AssociationWidgetList UMLScene::selectedAssocs() { AssociationWidgetList assocWidgetList; foreach(AssociationWidget* assocwidget, associationList()) { if (assocwidget->isSelected()) assocWidgetList.append(assocwidget); } return assocWidgetList; } /** * Adds a floating text widget to the view */ void UMLScene::addFloatingTextWidget(FloatingTextWidget* pWidget) { int wX = pWidget->x(); int wY = pWidget->y(); bool xIsOutOfRange = (wX < sceneRect().left() || wX > sceneRect().right()); bool yIsOutOfRange = (wY < sceneRect().top() || wY > sceneRect().bottom()); if (xIsOutOfRange || yIsOutOfRange) { QString name = pWidget->name(); if (name.isEmpty()) { FloatingTextWidget *ft = pWidget->asFloatingTextWidget(); if (ft) name = ft->displayText(); } DEBUG(DBG_SRC) << name << " type=" << pWidget->baseTypeStr() << ": position (" << wX << "," << wY << ") is out of range"; if (xIsOutOfRange) { pWidget->setX(0); wX = 0; } if (yIsOutOfRange) { pWidget->setY(0); wY = 0; } } addWidgetCmd(pWidget); } /** * Adds an association to the view from the given data. * Use this method when pasting. */ bool UMLScene::addAssociation(AssociationWidget* pAssoc, bool isPasteOperation) { if (!pAssoc) { return false; } const Uml::AssociationType::Enum assocType = pAssoc->associationType(); if (isPasteOperation) { IDChangeLog * log = m_doc->changeLog(); if (!log) { return false; } Uml::ID::Type ida = Uml::ID::None, idb = Uml::ID::None; if (type() == DiagramType::Collaboration || type() == DiagramType::Sequence) { //check local log first ida = m_pIDChangesLog->findNewID(pAssoc->widgetIDForRole(Uml::RoleType::A)); idb = m_pIDChangesLog->findNewID(pAssoc->widgetIDForRole(Uml::RoleType::B)); //if either is still not found and assoc type is anchor //we are probably linking to a notewidet - else an error if (ida == Uml::ID::None && assocType == Uml::AssociationType::Anchor) ida = log->findNewID(pAssoc->widgetIDForRole(Uml::RoleType::A)); if (idb == Uml::ID::None && assocType == Uml::AssociationType::Anchor) idb = log->findNewID(pAssoc->widgetIDForRole(Uml::RoleType::B)); } else { Uml::ID::Type oldIdA = pAssoc->widgetIDForRole(Uml::RoleType::A); Uml::ID::Type oldIdB = pAssoc->widgetIDForRole(Uml::RoleType::B); ida = log->findNewID(oldIdA); if (ida == Uml::ID::None) { // happens after a cut if (oldIdA == Uml::ID::None) { return false; } ida = oldIdA; } idb = log->findNewID(oldIdB); if (idb == Uml::ID::None) { // happens after a cut if (oldIdB == Uml::ID::None) { return false; } idb = oldIdB; } } if (ida == Uml::ID::None || idb == Uml::ID::None) { return false; } // cant do this anymore.. may cause problem for pasting // pAssoc->setWidgetID(ida, A); // pAssoc->setWidgetID(idb, B); pAssoc->setWidgetForRole(findWidget(ida), Uml::RoleType::A); pAssoc->setWidgetForRole(findWidget(idb), Uml::RoleType::B); } UMLWidget * pWidgetA = findWidget(pAssoc->widgetIDForRole(Uml::RoleType::A)); UMLWidget * pWidgetB = findWidget(pAssoc->widgetIDForRole(Uml::RoleType::B)); //make sure valid widget ids if (!pWidgetA || !pWidgetB) { return false; } //make sure there isn't already the same assoc foreach(AssociationWidget* assocwidget, associationList()) { if (*pAssoc == *assocwidget) // this is nuts. Paste operation wants to know if 'true' // for duplicate, but loadFromXMI1 needs 'false' value return (isPasteOperation ? true : false); } addWidgetCmd(pAssoc); FloatingTextWidget *ft[5] = { pAssoc->nameWidget(), pAssoc->roleWidget(Uml::RoleType::A), pAssoc->roleWidget(Uml::RoleType::B), pAssoc->multiplicityWidget(Uml::RoleType::A), pAssoc->multiplicityWidget(Uml::RoleType::B) }; for (int i = 0; i < 5; i++) { FloatingTextWidget *flotxt = ft[i]; if (flotxt) { flotxt->updateGeometry(); addFloatingTextWidget(flotxt); } } return true; } /** * Activate the view after a load a new file */ void UMLScene::activateAfterLoad(bool bUseLog) { if (m_isActivated) { return; } if (bUseLog) { beginPartialWidgetPaste(); } //now activate them all activate(); if (bUseLog) { endPartialWidgetPaste(); } m_view->centerOn(0, 0); m_isActivated = true; } void UMLScene::beginPartialWidgetPaste() { delete m_pIDChangesLog; m_pIDChangesLog = 0; m_pIDChangesLog = new IDChangeLog(); m_bPaste = true; } void UMLScene::endPartialWidgetPaste() { delete m_pIDChangesLog; m_pIDChangesLog = 0; m_bPaste = false; } /** * Removes a AssociationWidget from a diagram * Physically deletes the AssociationWidget passed in. * * @param pAssoc Pointer to the AssociationWidget. */ void UMLScene::removeWidgetCmd(AssociationWidget* pAssoc) { if (!pAssoc) return; emit sigAssociationRemoved(pAssoc); pAssoc->cleanup(); removeItem(pAssoc); pAssoc->deleteLater(); m_doc->setModified(); } /** * Removes an AssociationWidget from the association list * and removes the corresponding UMLAssociation from the current UMLDoc. */ void UMLScene::removeAssocInViewAndDoc(AssociationWidget* a) { // For umbrello 1.2, UMLAssociations can only be removed in two ways: // 1. Right click on the assocwidget in the view and select Delete // 2. Go to the Class Properties page, select Associations, right click // on the association and select Delete if (!a) return; if (a->associationType() == Uml::AssociationType::Containment) { UMLObject *objToBeMoved = a->widgetForRole(Uml::RoleType::B)->umlObject(); if (objToBeMoved != 0) { UMLListView *lv = UMLApp::app()->listView(); lv->moveObject(objToBeMoved->id(), Model_Utils::convert_OT_LVT(objToBeMoved), lv->theLogicalView()); // UMLListView::moveObject() will delete the containment // AssociationWidget via UMLScene::updateContainment(). } else { DEBUG(DBG_SRC) << "removeAssocInViewAndDoc(containment): " << "objB is NULL"; } } else { // Remove assoc in doc. m_doc->removeAssociation(a->association()); // Remove assoc in view. removeWidgetCmd(a); } } /** * Removes all the associations related to Widget. * * @param widget Pointer to the widget to remove. */ void UMLScene::removeAssociations(UMLWidget* widget) { foreach(AssociationWidget* assocwidget, associationList()) { if (assocwidget->containsAsEndpoint(widget)) { removeWidgetCmd(assocwidget); } } } /** * Sets each association as selected if the widgets it associates are selected * * @param bSelect True to select, false for unselect */ void UMLScene::selectAssociations(bool bSelect) { foreach(AssociationWidget* assocwidget, associationList()) { UMLWidget *widA = assocwidget->widgetForRole(Uml::RoleType::A); UMLWidget *widB = assocwidget->widgetForRole(Uml::RoleType::B); if (bSelect && widA && widA->isSelected() && widB && widB->isSelected()) { assocwidget->setSelected(true); } else { assocwidget->setSelected(false); } } } /** * Fills Associations with all the associations that includes a widget related to object */ void UMLScene::getWidgetAssocs(UMLObject* Obj, AssociationWidgetList & Associations) { if (! Obj) return; foreach(AssociationWidget* assocwidget, associationList()) { if (assocwidget->widgetForRole(Uml::RoleType::A)->umlObject() == Obj || assocwidget->widgetForRole(Uml::RoleType::B)->umlObject() == Obj) Associations.append(assocwidget); } } /** * Removes All the associations of the diagram */ void UMLScene::removeAllAssociations() { //Remove All association widgets foreach(AssociationWidget* assocwidget, associationList()) { removeWidgetCmd(assocwidget); } } /** * Removes All the widgets of the diagram */ void UMLScene::removeAllWidgets() { // Remove widgets. foreach(UMLWidget* temp, widgetList()) { uIgnoreZeroPointer(temp); // I had to take this condition back in, else umbrello // crashes on exit. Still to be analyzed. --okellogg if (!(temp->isTextWidget() && temp->asFloatingTextWidget()->textRole() != TextRole::Floating)) { removeWidgetCmd(temp); } } } /** * Refreshes containment association, i.e. removes possible old * containment and adds new containment association if applicable. * * @param self Pointer to the contained object for which * the association to the containing object is * recomputed. */ void UMLScene::updateContainment(UMLCanvasObject *self) { if (self == 0) return; // See if the object has a widget representation in this view. // While we're at it, also see if the new parent has a widget here. UMLWidget *selfWidget = 0, *newParentWidget = 0; UMLPackage *newParent = self->umlPackage(); foreach(UMLWidget* w, widgetList()) { UMLObject *o = w->umlObject(); if (o == self) selfWidget = w; else if (newParent != 0 && o == newParent) newParentWidget = w; } if (selfWidget == 0) return; // Remove possibly obsoleted containment association. foreach(AssociationWidget* a, associationList()) { if (a->associationType() != Uml::AssociationType::Containment) continue; // Container is at role A, containee at B. // We only look at association for which we are B. UMLWidget *wB = a->widgetForRole(Uml::RoleType::B); UMLObject *roleBObj = wB->umlObject(); if (roleBObj != self) continue; UMLWidget *wA = a->widgetForRole(Uml::RoleType::A); UMLObject *roleAObj = wA->umlObject(); if (roleAObj == newParent) { // Wow, all done. Great! return; } removeWidgetCmd(a); // It's okay to break out because there can only be a single // containing object. break; } if (newParentWidget == 0) return; // Create the new containment association. AssociationWidget *a = AssociationWidget::create (this, newParentWidget, Uml::AssociationType::Containment, selfWidget); addWidgetCmd(a); } /** * Creates automatically any Associations that the given @ref UMLWidget * may have on any diagram. This method is used when you just add the UMLWidget * to a diagram. */ void UMLScene::createAutoAssociations(UMLWidget * widget) { if (widget == 0 || (m_Type != Uml::DiagramType::Class && m_Type != Uml::DiagramType::Object && m_Type != Uml::DiagramType::Component && m_Type != Uml::DiagramType::Deployment && m_Type != Uml::DiagramType::EntityRelationship)) return; // Recipe: // If this widget has an underlying UMLCanvasObject then // for each of the UMLCanvasObject's UMLAssociations // if umlassoc's "other" role has a widget representation on this view then // if the AssocWidget does not already exist then // if the assoc type is permitted in the current diagram type then // create the AssocWidget // end if // end if // end if // end loop // Do createAutoAttributeAssociations() // if this object is capable of containing nested objects then // for each of the object's containedObjects // if the containedObject has a widget representation on this view then // if the containedWidget is not physically located inside this widget // create the containment AssocWidget // end if // end if // end loop // end if // if the UMLCanvasObject has a parentPackage then // if the parentPackage has a widget representation on this view then // create the containment AssocWidget // end if // end if // end if UMLObject *tmpUmlObj = widget->umlObject(); if (tmpUmlObj == 0) return; UMLCanvasObject *umlObj = tmpUmlObj->asUMLCanvasObject(); if (umlObj == 0) return; const UMLAssociationList& umlAssocs = umlObj->getAssociations(); Uml::ID::Type myID = umlObj->id(); foreach(UMLAssociation* assoc, umlAssocs) { UMLCanvasObject *other = 0; UMLObject *roleAObj = assoc->getObject(Uml::RoleType::A); if (roleAObj == 0) { DEBUG(DBG_SRC) << "roleA object is NULL at UMLAssoc " << Uml::ID::toString(assoc->id()); continue; } UMLObject *roleBObj = assoc->getObject(Uml::RoleType::B); if (roleBObj == 0) { DEBUG(DBG_SRC) << "roleB object is NULL at UMLAssoc " << Uml::ID::toString(assoc->id()); continue; } if (roleAObj->id() == myID) { other = roleBObj->asUMLCanvasObject(); } else if (roleBObj->id() == myID) { other = roleAObj->asUMLCanvasObject(); } else { DEBUG(DBG_SRC) << "Cannot find own object " << Uml::ID::toString(myID) << " in UMLAssoc " << Uml::ID::toString(assoc->id()); continue; } // Now that we have determined the "other" UMLObject, seek it in // this view's UMLWidgets. if (!other) { continue; } Uml::ID::Type otherID = other->id(); bool breakFlag = false; UMLWidget* pOtherWidget = 0; foreach(pOtherWidget, widgetList()) { if (pOtherWidget->id() == otherID) { breakFlag = true; break; } } if (!breakFlag) continue; // Both objects are represented in this view: // Assign widget roles as indicated by the UMLAssociation. UMLWidget *widgetA, *widgetB; if (myID == roleAObj->id()) { widgetA = widget; widgetB = pOtherWidget; } else { widgetA = pOtherWidget; widgetB = widget; } // Check that the assocwidget does not already exist. Uml::AssociationType::Enum assocType = assoc->getAssocType(); AssociationWidget * assocwidget = findAssocWidget(assocType, widgetA, widgetB); if (assocwidget) { assocwidget->calculateEndingPoints(); // recompute assoc lines continue; } // Check that the assoc is allowed. if (!AssocRules::allowAssociation(assocType, widgetA, widgetB)) { DEBUG(DBG_SRC) << "not transferring assoc " << "of type " << assocType; continue; } // Create the AssociationWidget. assocwidget = AssociationWidget::create(this); assocwidget->setWidgetForRole(widgetA, Uml::RoleType::A); assocwidget->setWidgetForRole(widgetB, Uml::RoleType::B); assocwidget->setAssociationType(assocType); assocwidget->setUMLObject(assoc); // Call calculateEndingPoints() before setting the FloatingTexts // because their positions are computed according to the // assocwidget line positions. assocwidget->calculateEndingPoints(); assocwidget->syncToModel(); assocwidget->setActivated(true); if (! addAssociation(assocwidget)) delete assocwidget; } createAutoAttributeAssociations(widget); if (m_Type == Uml::DiagramType::EntityRelationship) { createAutoConstraintAssociations(widget); } // if this object is capable of containing nested objects then UMLObject::ObjectType t = umlObj->baseType(); if (t == UMLObject::ot_Package || t == UMLObject::ot_Class || t == UMLObject::ot_Interface || t == UMLObject::ot_Component) { // for each of the object's containedObjects UMLPackage *umlPkg = umlObj->asUMLPackage(); UMLObjectList lst = umlPkg->containedObjects(); foreach(UMLObject* obj, lst) { uIgnoreZeroPointer(obj); // if the containedObject has a widget representation on this view then Uml::ID::Type id = obj->id(); foreach(UMLWidget *w, widgetList()) { uIgnoreZeroPointer(w); if (w->id() != id) continue; // if the containedWidget is not physically located inside this widget if (widget->rect().contains(w->rect())) continue; // create the containment AssocWidget AssociationWidget *a = AssociationWidget::create(this, widget, Uml::AssociationType::Containment, w); a->calculateEndingPoints(); a->setActivated(true); if (! addAssociation(a)) delete a; } } } // if the UMLCanvasObject has a parentPackage then UMLPackage *parent = umlObj->umlPackage(); if (parent == 0) return; // if the parentPackage has a widget representation on this view then Uml::ID::Type pkgID = parent->id(); bool breakFlag = false; UMLWidget* pWidget = 0; foreach(pWidget, widgetList()) { uIgnoreZeroPointer(pWidget); if (pWidget->id() == pkgID) { breakFlag = true; break; } } if (!breakFlag || pWidget->rect().contains(widget->rect())) return; // create the containment AssocWidget AssociationWidget *a = AssociationWidget::create(this, pWidget, Uml::AssociationType::Containment, widget); if (! addAssociation(a)) delete a; } /** * If the m_Type of the given widget is WidgetBase::wt_Class then * iterate through the class' attributes and create an * association to each attribute type widget that is present * on the current diagram. */ void UMLScene::createAutoAttributeAssociations(UMLWidget *widget) { if (widget == 0 || m_Type != Uml::DiagramType::Class || !m_Options.classState.showAttribAssocs) return; // Pseudocode: // if the underlying model object is really a UMLClassifier then // for each of the UMLClassifier's UMLAttributes // if the attribute type has a widget representation on this view then // if the AssocWidget does not already exist then // if the current diagram type permits compositions then // create a composition AssocWidget // end if // end if // end if // if the attribute type is a Datatype then // if the Datatype is a reference (pointer) type then // if the referenced type has a widget representation on this view then // if the AssocWidget does not already exist then // if the current diagram type permits aggregations then // create an aggregation AssocWidget from the ClassifierWidget to the // widget of the referenced type // end if // end if // end if // end if // end if // end loop // end if // // Implementation: UMLObject *tmpUmlObj = widget->umlObject(); if (tmpUmlObj == 0) return; // if the underlying model object is really a UMLClassifier then if (tmpUmlObj->isUMLDatatype()) { UMLDatatype *dt = tmpUmlObj->asUMLDatatype(); while (dt && dt->originType() != 0) { tmpUmlObj = dt->originType(); if (!tmpUmlObj->isUMLDatatype()) break; dt = tmpUmlObj->asUMLDatatype(); } } if (tmpUmlObj->baseType() != UMLObject::ot_Class) return; UMLClassifier * klass = tmpUmlObj->asUMLClassifier(); // for each of the UMLClassifier's UMLAttributes UMLAttributeList attrList = klass->getAttributeList(); foreach(UMLAttribute* attr, attrList) { createAutoAttributeAssociation(attr->getType(), attr, widget); /* * The following code from attachment 19935 of http://bugs.kde.org/140669 * creates Aggregation/Composition to the template parameters. * The current solution uses Dependency instead, see handling of template * instantiation at Import_Utils::createUMLObject(). UMLClassifierList templateList = attr->getTemplateParams(); for (UMLClassifierListIt it(templateList); it.current(); ++it) { createAutoAttributeAssociation(it, attr, widget); } */ } } /** * Create an association with the attribute attr associated with the UMLWidget * widget if the UMLClassifier type is present on the current diagram. */ void UMLScene::createAutoAttributeAssociation(UMLClassifier *type, UMLAttribute *attr, UMLWidget *widget /*, UMLClassifier * klass*/) { if (type == 0) { // DEBUG(DBG_SRC) << klass->getName() << ": type is NULL for " // << "attribute " << attr->getName(); return; } Uml::AssociationType::Enum assocType = Uml::AssociationType::Composition; UMLWidget *w = findWidget(type->id()); // if the attribute type has a widget representation on this view if (w) { AssociationWidget *a = findAssocWidget(widget, w, attr->name()); if (a == 0 && // if the current diagram type permits compositions AssocRules::allowAssociation(assocType, widget, w)) { // Create a composition AssocWidget, or, if the attribute type is // stereotyped <>, create a UniAssociation widget. if (type->stereotype() == QLatin1String("CORBAInterface")) assocType = Uml::AssociationType::UniAssociation; a = AssociationWidget::create(this, widget, assocType, w, attr); a->setVisibility(attr->visibility(), Uml::RoleType::B); /* if (assocType == Uml::AssociationType::Aggregation || assocType == Uml::AssociationType::UniAssociation) a->setMulti("0..1", Uml::RoleType::B); */ a->setRoleName(attr->name(), Uml::RoleType::B); a->setActivated(true); if (! addAssociation(a)) delete a; } } // if the attribute type is a Datatype then if (type->isUMLDatatype()) { UMLDatatype *dt = type->asUMLDatatype(); // if the Datatype is a reference (pointer) type if (dt && dt->isReference()) { //Uml::AssociationType::Enum assocType = Uml::AssociationType::Composition; UMLClassifier *c = dt->originType(); UMLWidget *w = c ? findWidget(c->id()) : 0; // if the referenced type has a widget representation on this view if (w) { AssociationWidget *a = findAssocWidget(widget, w, attr->name()); if (a == 0 && // if the current diagram type permits aggregations AssocRules::allowAssociation(Uml::AssociationType::Aggregation, widget, w)) { // create an aggregation AssocWidget from the ClassifierWidget // to the widget of the referenced type a = AssociationWidget::create (this, widget, Uml::AssociationType::Aggregation, w, attr); a->setVisibility(attr->visibility(), Uml::RoleType::B); //a->setChangeability(true, Uml::RoleType::B); a->setMultiplicity(QLatin1String("0..1"), Uml::RoleType::B); a->setRoleName(attr->name(), Uml::RoleType::B); a->setActivated(true); if (! addAssociation(a)) delete a; } } } } } void UMLScene::createAutoConstraintAssociations(UMLWidget *widget) { if (widget == 0 || m_Type != Uml::DiagramType::EntityRelationship) return; // Pseudocode: // if the underlying model object is really a UMLEntity then // for each of the UMLEntity's UMLForeignKeyConstraint's // if the attribute type has a widget representation on this view then // if the AssocWidget does not already exist then // if the current diagram type permits relationships then // create a relationship AssocWidget // end if // end if // end if UMLObject *tmpUmlObj = widget->umlObject(); if (tmpUmlObj == 0) return; // check if the underlying model object is really a UMLEntity UMLCanvasObject *umlObj = tmpUmlObj->asUMLCanvasObject(); if (umlObj == 0) return; // finished checking whether this widget has a UMLCanvas Object if (tmpUmlObj->baseType() != UMLObject::ot_Entity) return; UMLEntity *entity = tmpUmlObj->asUMLEntity(); // for each of the UMLEntity's UMLForeignKeyConstraints UMLClassifierListItemList constrList = entity->getFilteredList(UMLObject::ot_ForeignKeyConstraint); foreach(UMLClassifierListItem* cli, constrList) { UMLEntityConstraint *eConstr = cli->asUMLEntityConstraint(); UMLForeignKeyConstraint* fkc = eConstr->asUMLForeignKeyConstraint(); if (fkc == 0) { return; } UMLEntity* refEntity = fkc->getReferencedEntity(); if (refEntity == 0) { return; } createAutoConstraintAssociation(refEntity, fkc, widget); } } void UMLScene::createAutoConstraintAssociation(UMLEntity* refEntity, UMLForeignKeyConstraint* fkConstraint, UMLWidget* widget) { if (refEntity == 0) { return; } Uml::AssociationType::Enum assocType = Uml::AssociationType::Relationship; UMLWidget *w = findWidget(refEntity->id()); AssociationWidget *aw = 0; if (w) { aw = findAssocWidget(w, widget, fkConstraint->name()); if (aw == 0 && // if the current diagram type permits relationships AssocRules::allowAssociation(assocType, w, widget)) { // for foreign key contstraint, we need to create the association type Uml::AssociationType::Relationship. // The referenced entity is the "1" part (Role A) and the entity holding the relationship is the "many" part. (Role B) AssociationWidget *a = AssociationWidget::create(this, w, assocType, widget); a->setUMLObject(fkConstraint); //a->setVisibility(attr->getVisibility(), Uml::RoleType::B); a->setRoleName(fkConstraint->name(), Uml::RoleType::B); a->setActivated(true); if (! addAssociation(a)) delete a; } } } void UMLScene::createAutoAttributeAssociations2(UMLWidget *widget) { foreach(UMLWidget* w, widgetList()) { uIgnoreZeroPointer(w); if (w != widget) { createAutoAttributeAssociations(w); if (widget->umlObject() && widget->umlObject()->baseType() == UMLObject::ot_Entity) createAutoConstraintAssociations(w); } } } /** * Find the maximum bounding rectangle of FloatingTextWidget widgets. * Auxiliary to copyAsImage(). * * @param ft Pointer to the FloatingTextWidget widget to consider. * @param px X coordinate of lower left corner. This value will be * updated if the X coordinate of the lower left corner * of ft is smaller than the px value passed in. * @param py Y coordinate of lower left corner. This value will be * updated if the Y coordinate of the lower left corner * of ft is smaller than the py value passed in. * @param qx X coordinate of upper right corner. This value will be * updated if the X coordinate of the upper right corner * of ft is larger than the qx value passed in. * @param qy Y coordinate of upper right corner. This value will be * updated if the Y coordinate of the upper right corner * of ft is larger than the qy value passed in. */ void UMLScene::findMaxBoundingRectangle(const FloatingTextWidget* ft, qreal& px, qreal& py, qreal& qx, qreal& qy) { if (ft == 0 || !ft->isVisible()) return; qreal x = ft->x(); qreal y = ft->y(); qreal x1 = x + ft->width() - 1; qreal y1 = y + ft->height() - 1; if (px == -1 || x < px) px = x; if (py == -1 || y < py) py = y; if (qx == -1 || x1 > qx) qx = x1; if (qy == -1 || y1 > qy) qy = y1; } /** * Returns the PNG picture of the paste operation. */ void UMLScene::copyAsImage(QPixmap*& pix) { //get the smallest rect holding the diagram QRectF rect = diagramRect(); QPixmap diagram(rect.width(), rect.height()); //only draw what is selected m_bDrawSelectedOnly = true; selectAssociations(true); getDiagram(diagram, rect); //now get the selection cut qreal px = -1, py = -1, qx = -1, qy = -1; //first get the smallest rect holding the widgets foreach(UMLWidget* temp, selectedWidgets()) { qreal x = temp->x(); qreal y = temp->y(); qreal x1 = x + temp->width() - 1; qreal y1 = y + temp->height() - 1; if (px == -1 || x < px) { px = x; } if (py == -1 || y < py) { py = y; } if (qx == -1 || x1 > qx) { qx = x1; } if (qy == -1 || y1 > qy) { qy = y1; } } //also take into account any text lines in assocs or messages //get each type of associations //This needs to be reimplemented to increase the rectangle //if a part of any association is not included foreach(AssociationWidget *a, associationList()) { if (! a->isSelected()) continue; const FloatingTextWidget* multiA = a->multiplicityWidget(Uml::RoleType::A); const FloatingTextWidget* multiB = a->multiplicityWidget(Uml::RoleType::B); const FloatingTextWidget* roleA = a->roleWidget(Uml::RoleType::A); const FloatingTextWidget* roleB = a->roleWidget(Uml::RoleType::B); const FloatingTextWidget* changeA = a->changeabilityWidget(Uml::RoleType::A); const FloatingTextWidget* changeB = a->changeabilityWidget(Uml::RoleType::B); findMaxBoundingRectangle(multiA, px, py, qx, qy); findMaxBoundingRectangle(multiB, px, py, qx, qy); findMaxBoundingRectangle(roleA, px, py, qx, qy); findMaxBoundingRectangle(roleB, px, py, qx, qy); findMaxBoundingRectangle(changeA, px, py, qx, qy); findMaxBoundingRectangle(changeB, px, py, qx, qy); }//end foreach QRectF imageRect; //area with respect to diagramRect() //i.e. all widgets on the scene. Was previously with //respect to whole scene imageRect.setLeft(px - rect.left()); imageRect.setTop(py - rect.top()); imageRect.setRight(qx - rect.left()); imageRect.setBottom(qy - rect.top()); pix = new QPixmap(imageRect.width(), imageRect.height()); QPainter output(pix); output.drawPixmap(QPoint(0, 0), diagram, imageRect); m_bDrawSelectedOnly = false; } /** * Reset the toolbar. */ void UMLScene::resetToolbar() { emit sigResetToolBar(); } /** * Event handler for context menu events. */ void UMLScene::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) { QGraphicsScene::contextMenuEvent(event); if (!event->isAccepted()) { setPos(event->scenePos()); UMLScenePopupMenu popup(m_view, this); QAction *triggered = popup.exec(event->screenPos()); slotMenuSelection(triggered); event->accept(); } } /** * Returns the status on whether in a paste state. * * @return Returns the status on whether in a paste state. */ bool UMLScene::getPaste() const { return m_bPaste; } /** * Sets the status on whether in a paste state. */ void UMLScene::setPaste(bool paste) { m_bPaste = paste; } /** * When a menu selection has been made on the menu * that this view created, this method gets called. */ void UMLScene::slotMenuSelection(QAction* action) { ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(action); switch (sel) { case ListPopupMenu::mt_Undo: UMLApp::app()->undo(); break; case ListPopupMenu::mt_Redo: UMLApp::app()->redo(); break; case ListPopupMenu::mt_Clear: clearDiagram(); break; case ListPopupMenu::mt_Export_Image: m_pImageExporter->exportView(); break; case ListPopupMenu::mt_Apply_Layout: case ListPopupMenu::mt_Apply_Layout1: case ListPopupMenu::mt_Apply_Layout2: case ListPopupMenu::mt_Apply_Layout3: case ListPopupMenu::mt_Apply_Layout4: case ListPopupMenu::mt_Apply_Layout5: case ListPopupMenu::mt_Apply_Layout6: case ListPopupMenu::mt_Apply_Layout7: case ListPopupMenu::mt_Apply_Layout8: case ListPopupMenu::mt_Apply_Layout9: { QVariant value = ListPopupMenu::dataFromAction(ListPopupMenu::dt_ApplyLayout, action); applyLayout(value.toString()); } break; case ListPopupMenu::mt_FloatText: { FloatingTextWidget* ft = new FloatingTextWidget(this); ft->showChangeTextDialog(); //if no text entered delete if (!FloatingTextWidget::isTextValid(ft->text())) { delete ft; } else { ft->setID(UniqueID::gen()); setupNewWidget(ft); } } break; case ListPopupMenu::mt_UseCase: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_UseCase); break; case ListPopupMenu::mt_Actor: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Actor); break; case ListPopupMenu::mt_Class: case ListPopupMenu::mt_Object: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Class); break; case ListPopupMenu::mt_Package: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Package); break; case ListPopupMenu::mt_Subsystem: { m_bCreateObject = true; UMLPackage *component = UMLApp::app()->document()->rootFolder(Uml::ModelType::Component); QString name = Model_Utils::uniqObjectName(UMLObject::ot_Package, component, i18n("new_subsystem")); if (Dialog_Utils::askName(i18n("Enter Subsystem Name"), i18n("Enter the name of the new subsystem"), name)) { UMLObject *package = Object_Factory::createUMLObject(UMLObject::ot_Package, name, component); if (package) package->setStereotypeCmd(QLatin1String("subsystem")); } break; } case ListPopupMenu::mt_Component: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Component); break; case ListPopupMenu::mt_Node: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Node); break; case ListPopupMenu::mt_Artifact: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Artifact); break; case ListPopupMenu::mt_Interface: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Interface); break; case ListPopupMenu::mt_Enum: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Enum); break; case ListPopupMenu::mt_Entity: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Entity); break; case ListPopupMenu::mt_Category: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Category); break; case ListPopupMenu::mt_Datatype: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Datatype); break; case ListPopupMenu::mt_Instance: m_bCreateObject = true; Object_Factory::createUMLObject(UMLObject::ot_Instance); break; case ListPopupMenu::mt_Note: { m_bCreateObject = true; UMLWidget* widget = new NoteWidget(this); addItem(widget); widget->setPos(pos()); widget->setSize(100, 40); widget->showPropertiesDialog(); QSizeF size = widget->minimumSize(); widget->setSize(size); break; } case ListPopupMenu::mt_Cut: //FIXME make this work for diagram's right click menu if (selectedWidgets().count() && UMLApp::app()->editCutCopy(true)) { deleteSelection(); m_doc->setModified(true); } break; case ListPopupMenu::mt_Copy: //FIXME make this work for diagram's right click menu selectedWidgets().count() && UMLApp::app()->editCutCopy(true); break; case ListPopupMenu::mt_Paste: m_PastePoint = m_Pos; m_Pos.setX(2000); m_Pos.setY(2000); UMLApp::app()->slotEditPaste(); m_PastePoint.setX(0); m_PastePoint.setY(0); break; case ListPopupMenu::mt_Initial_State: { StateWidget* state = new StateWidget(this, StateWidget::Initial); setupNewWidget(state); } break; case ListPopupMenu::mt_End_State: { StateWidget* state = new StateWidget(this, StateWidget::End); setupNewWidget(state); } break; case ListPopupMenu::mt_Junction: { StateWidget* state = new StateWidget(this, StateWidget::Junction); setupNewWidget(state); } break; case ListPopupMenu::mt_DeepHistory: { StateWidget* state = new StateWidget(this, StateWidget::DeepHistory); setupNewWidget(state); } break; case ListPopupMenu::mt_ShallowHistory: { StateWidget* state = new StateWidget(this, StateWidget::ShallowHistory); setupNewWidget(state); } break; case ListPopupMenu::mt_Choice: { StateWidget* state = new StateWidget(this, StateWidget::Choice); setupNewWidget(state); } break; case ListPopupMenu::mt_StateFork: { StateWidget* state = new StateWidget(this, StateWidget::Fork); setupNewWidget(state); } break; case ListPopupMenu::mt_StateJoin: { StateWidget* state = new StateWidget(this, StateWidget::Join); setupNewWidget(state); } break; case ListPopupMenu::mt_State: { QString name = i18n("new state"); bool ok = Dialog_Utils::askName(i18n("Enter State Name"), i18n("Enter the name of the new state:"), name); if (ok) { StateWidget* state = new StateWidget(this); state->setName(name); setupNewWidget(state); } } break; case ListPopupMenu::mt_Initial_Activity: { ActivityWidget* activity = new ActivityWidget(this, ActivityWidget::Initial); setupNewWidget(activity); } break; case ListPopupMenu::mt_End_Activity: { ActivityWidget* activity = new ActivityWidget(this, ActivityWidget::End); setupNewWidget(activity); } break; case ListPopupMenu::mt_Branch: { ActivityWidget* activity = new ActivityWidget(this, ActivityWidget::Branch); setupNewWidget(activity); } break; case ListPopupMenu::mt_Activity: { QString name = i18n("new activity"); bool ok = Dialog_Utils::askName(i18n("Enter Activity Name"), i18n("Enter the name of the new activity:"), name); if (ok) { ActivityWidget* activity = new ActivityWidget(this, ActivityWidget::Normal); activity->setName(name); setupNewWidget(activity); } } break; case ListPopupMenu::mt_SnapToGrid: toggleSnapToGrid(); m_doc->setModified(); break; case ListPopupMenu::mt_SnapComponentSizeToGrid: toggleSnapComponentSizeToGrid(); m_doc->setModified(); break; case ListPopupMenu::mt_ShowSnapGrid: toggleShowGrid(); m_doc->setModified(); break; case ListPopupMenu::mt_ShowDocumentationIndicator: setShowDocumentationIndicator(!isShowDocumentationIndicator()); update(); break; case ListPopupMenu::mt_Properties: if (m_view->showPropertiesDialog() == true) m_doc->setModified(); break; case ListPopupMenu::mt_Delete: m_doc->removeDiagram(ID()); break; case ListPopupMenu::mt_Rename: { QString newName = name(); bool ok = Dialog_Utils::askName(i18n("Enter Diagram Name"), i18n("Enter the new name of the diagram:"), newName); if (ok) { setName(newName); m_doc->signalDiagramRenamed(activeView()); } } break; case ListPopupMenu::mt_Import_from_File: { QPointer dialog = new UMLFileDialog(QUrl(), QString(), UMLApp::app()); dialog->exec(); QUrl url = dialog->selectedUrl(); if (!url.isEmpty()) if (!Diagram_Utils::importGraph(url.toLocalFile(), this)) UMLApp::app()->slotStatusMsg(i18n("Failed to import from file.")); break; } default: uWarning() << "unknown ListPopupMenu::MenuType " << ListPopupMenu::toString(sel); break; } } /** * Connects to the signal that @ref UMLApp emits when a cut operation * is successful. * If the view or a child started the operation the flag m_bStartedCut will * be set and we can carry out any operation that is needed, like deleting the selected * widgets for the cut operation. */ void UMLScene::slotCutSuccessful() { if (m_bStartedCut) { deleteSelection(); m_bStartedCut = false; } } /** * Called by menu when to show the instance of the view. */ void UMLScene::slotShowView() { m_doc->changeCurrentView(ID()); } /** * Returns the offset point at which to place the paste from clipboard. * Just add the amount to your co-ords. * Only call this straight after the event, the value won't stay valid. * Should only be called by Assoc widgets at the moment. no one else needs it. */ QPointF UMLScene::getPastePoint() { QPointF point = m_PastePoint; point.setX(point.x() - m_Pos.x()); point.setY(point.y() - m_Pos.y()); return point; } /** * Reset the paste point. */ void UMLScene::resetPastePoint() { m_PastePoint = m_Pos; } /** * Called by the view or any of its children when they start a cut * operation. */ void UMLScene::setStartedCut() { m_bStartedCut = true; } /** * Returns the font to use */ QFont UMLScene::font() const { return m_Options.uiState.font; } /** * Sets the font for the view and optionally all the widgets on the view. */ void UMLScene::setFont(QFont font, bool changeAllWidgets /* = false */) { m_Options.uiState.font = font; if (!changeAllWidgets) return; foreach(UMLWidget* w, widgetList()) { uIgnoreZeroPointer(w); w->setFont(font); } } /** * Sets some options for all the @ref ClassifierWidget on the view. */ void UMLScene::setClassWidgetOptions(ClassOptionsPage * page) { foreach(UMLWidget* pWidget, widgetList()) { uIgnoreZeroPointer(pWidget); WidgetBase::WidgetType wt = pWidget->baseType(); - if (wt == WidgetBase::wt_Class || wt == WidgetBase::wt_Interface) { - page->setWidget(static_cast(pWidget)); + if (wt == WidgetBase::wt_Class) { + page->setWidget(pWidget->asClassifierWidget()); + page->apply(); + } else if (wt == WidgetBase::wt_Interface) { + page->setWidget(pWidget->asInterfaceWidget()); page->apply(); } } } /** * Returns the type of the selected widget or widgets. * * If multiple widgets of different types are selected. WidgetType::UMLWidget * is returned. */ WidgetBase::WidgetType UMLScene::getUniqueSelectionType() { if (selectedWidgets().isEmpty()) { return WidgetBase::wt_UMLWidget; } // Get the first item and its base type UMLWidget * pTemp = (UMLWidget *) selectedWidgets().first(); WidgetBase::WidgetType tmpType = pTemp->baseType(); // Check all selected items, if they have the same BaseType foreach(pTemp, selectedWidgets()) { if (pTemp->baseType() != tmpType) { return WidgetBase::wt_UMLWidget; } } return tmpType; } /** * Asks for confirmation and clears everything on the diagram. * Called from menus. */ void UMLScene::clearDiagram() { if (Dialog_Utils::askDeleteDiagram()) { removeAllWidgets(); } } /** * Apply an automatic layout. */ void UMLScene::applyLayout(const QString &variant) { DEBUG(DBG_SRC) << "layout = " << variant; LayoutGenerator r; r.generate(this, variant); r.apply(this); UMLApp::app()->slotZoomFit(); } /** * Changes snap to grid boolean. * Called from menus. */ void UMLScene::toggleSnapToGrid() { setSnapToGrid(!snapToGrid()); } /** * Changes snap to grid for component size boolean. * Called from menus. */ void UMLScene::toggleSnapComponentSizeToGrid() { setSnapComponentSizeToGrid(!snapComponentSizeToGrid()); } /** * Changes show grid boolean. * Called from menus. */ void UMLScene::toggleShowGrid() { setSnapGridVisible(!isSnapGridVisible()); } /** * Return whether to use snap to grid. */ bool UMLScene::snapToGrid() const { return m_bUseSnapToGrid; } /** * Sets whether to snap to grid. */ void UMLScene::setSnapToGrid(bool bSnap) { m_bUseSnapToGrid = bSnap; emit sigSnapToGridToggled(snapToGrid()); } /** * Return whether to use snap to grid for component size. */ bool UMLScene::snapComponentSizeToGrid() const { return m_bUseSnapComponentSizeToGrid; } /** * Sets whether to snap to grid for component size. */ void UMLScene::setSnapComponentSizeToGrid(bool bSnap) { m_bUseSnapComponentSizeToGrid = bSnap; updateComponentSizes(); emit sigSnapComponentSizeToGridToggled(snapComponentSizeToGrid()); } /** * Returns the x grid size. */ int UMLScene::snapX() const { return m_layoutGrid->gridSpacingX(); } /** * Returns the y grid size. */ int UMLScene::snapY() const { return m_layoutGrid->gridSpacingY(); } /** * Sets the grid size in x and y. */ void UMLScene::setSnapSpacing(int x, int y) { m_layoutGrid->setGridSpacing(x, y); } /** * Returns the input coordinate with possible grid-snap applied. */ qreal UMLScene::snappedX(qreal _x) { if (snapToGrid()) { int x = (int)_x; int gridX = snapX(); int modX = x % gridX; x -= modX; if (modX >= gridX / 2) x += gridX; return x; } else return _x; } /** * Returns the input coordinate with possible grid-snap applied. */ qreal UMLScene::snappedY(qreal _y) { if (snapToGrid()) { int y = (int)_y; int gridY = snapY(); int modY = y % gridY; y -= modY; if (modY >= gridY / 2) y += gridY; return y; } else return _y; } /** * Returns whether to show snap grid or not. */ bool UMLScene::isSnapGridVisible() const { return m_layoutGrid->isVisible(); } /** * Sets whether to show snap grid. */ void UMLScene::setSnapGridVisible(bool bShow) { m_layoutGrid->setVisible(bShow); emit sigShowGridToggled(bShow); } /** * Returns whether to show documentation indicator. */ bool UMLScene::isShowDocumentationIndicator() const { return m_showDocumentationIndicator; } /** * sets whether to show documentation indicator. */ void UMLScene::setShowDocumentationIndicator(bool bShow) { m_showDocumentationIndicator = bShow; } /** * Returns whether to show operation signatures. */ bool UMLScene::showOpSig() const { return m_Options.classState.showOpSig; } /** * Sets whether to show operation signatures. */ void UMLScene::setShowOpSig(bool bShowOpSig) { m_Options.classState.showOpSig = bShowOpSig; } /** * Changes the zoom to the currently set level (now loaded from file) * Called from UMLApp::slotUpdateViews() */ void UMLScene::fileLoaded() { m_view->setZoom(m_view->zoom()); resizeSceneToItems(); } /** * Sets the size of the scene to just fit on all the items */ void UMLScene::resizeSceneToItems() { // let QGraphicsScene handle scene size by itself setSceneRect(QRectF()); } /** * Updates the size of all components in this view. */ void UMLScene::updateComponentSizes() { // update sizes of all components foreach(UMLWidget *obj, widgetList()) { uIgnoreZeroPointer(obj); obj->updateGeometry(); } } /** * Force the widget font metrics to be updated next time * the widgets are drawn. * This is necessary because the widget size might depend on the * font metrics and the font metrics might change for different * QPainter, i.e. font metrics for Display font and Printer font are * usually different. * Call this when you change the QPainter. */ void UMLScene::forceUpdateWidgetFontMetrics(QPainter * painter) { foreach(UMLWidget *obj, widgetList()) { uIgnoreZeroPointer(obj); obj->forceUpdateFontMetrics(painter); } } /** * Overrides standard method from QGraphicsScene drawing the background. */ void UMLScene::drawBackground(QPainter *painter, const QRectF &rect) { QGraphicsScene::drawBackground(painter, rect); m_layoutGrid->paint(painter, rect); } /** * Creates the "diagram" tag and fills it with the contents of the diagram. */ void UMLScene::saveToXMI1(QDomDocument & qDoc, QDomElement & qElement) { resizeSceneToItems(); QDomElement viewElement = qDoc.createElement(QLatin1String("diagram")); viewElement.setAttribute(QLatin1String("xmi.id"), Uml::ID::toString(m_nID)); viewElement.setAttribute(QLatin1String("name"), name()); viewElement.setAttribute(QLatin1String("type"), m_Type); viewElement.setAttribute(QLatin1String("documentation"), m_Documentation); //option state m_Options.saveToXMI1(viewElement); //misc viewElement.setAttribute(QLatin1String("localid"), Uml::ID::toString(m_nLocalID)); viewElement.setAttribute(QLatin1String("showgrid"), m_layoutGrid->isVisible()); viewElement.setAttribute(QLatin1String("snapgrid"), m_bUseSnapToGrid); viewElement.setAttribute(QLatin1String("snapcsgrid"), m_bUseSnapComponentSizeToGrid); viewElement.setAttribute(QLatin1String("snapx"), m_layoutGrid->gridSpacingX()); viewElement.setAttribute(QLatin1String("snapy"), m_layoutGrid->gridSpacingY()); // FIXME: move to UMLView viewElement.setAttribute(QLatin1String("zoom"), activeView()->zoom()); viewElement.setAttribute(QLatin1String("canvasheight"), QString::number(height())); viewElement.setAttribute(QLatin1String("canvaswidth"), QString::number(width())); viewElement.setAttribute(QLatin1String("isopen"), isOpen()); if (type() == Uml::DiagramType::Sequence || type() == Uml::DiagramType::Collaboration) viewElement.setAttribute(QLatin1String("autoincrementsequence"), autoIncrementSequence()); //now save all the widgets QDomElement widgetElement = qDoc.createElement(QLatin1String("widgets")); foreach(UMLWidget *widget, widgetList()) { uIgnoreZeroPointer(widget); // do not save floating text widgets having a parent widget; they are saved as part of the parent if (widget->isTextWidget() && widget->parentItem()) continue; // Having an exception is bad I know, but gotta work with // system we are given. // We DON'T want to record any text widgets which are belonging // to associations as they are recorded later in the "associations" // section when each owning association is dumped. -b.t. if ((!widget->isTextWidget() && !widget->isFloatingDashLineWidget()) || (widget->asFloatingTextWidget() && widget->asFloatingTextWidget()->link() == 0)) widget->saveToXMI1(qDoc, widgetElement); } viewElement.appendChild(widgetElement); //now save the message widgets QDomElement messageElement = qDoc.createElement(QLatin1String("messages")); foreach(UMLWidget* widget, messageList()) { widget->saveToXMI1(qDoc, messageElement); } viewElement.appendChild(messageElement); //now save the associations QDomElement assocElement = qDoc.createElement(QLatin1String("associations")); if (associationList().count()) { // We guard against (associationList().count() == 0) because // this code could be reached as follows: // ^ UMLScene::saveToXMI1() // ^ UMLDoc::saveToXMI1() // ^ UMLDoc::addToUndoStack() // ^ UMLDoc::setModified() // ^ UMLDoc::createDiagram() // ^ UMLDoc::newDocument() // ^ UMLApp::newDocument() // ^ main() // AssociationWidget * assoc = 0; foreach(assoc, associationList()) { assoc->saveToXMI1(qDoc, assocElement); } } viewElement.appendChild(assocElement); qElement.appendChild(viewElement); } /** * Loads the "diagram" tag. */ bool UMLScene::loadFromXMI1(QDomElement & qElement) { QString id = qElement.attribute(QLatin1String("xmi.id"), QLatin1String("-1")); m_nID = Uml::ID::fromString(id); if (m_nID == Uml::ID::None) return false; setName(qElement.attribute(QLatin1String("name"))); QString type = qElement.attribute(QLatin1String("type"), QLatin1String("0")); m_Documentation = qElement.attribute(QLatin1String("documentation")); QString localid = qElement.attribute(QLatin1String("localid"), QLatin1String("0")); // option state m_Options.loadFromXMI1(qElement); setBackgroundBrush(m_Options.uiState.backgroundColor); setGridDotColor(m_Options.uiState.gridDotColor); //misc QString showgrid = qElement.attribute(QLatin1String("showgrid"), QLatin1String("0")); m_layoutGrid->setVisible((bool)showgrid.toInt()); QString snapgrid = qElement.attribute(QLatin1String("snapgrid"), QLatin1String("0")); m_bUseSnapToGrid = (bool)snapgrid.toInt(); QString snapcsgrid = qElement.attribute(QLatin1String("snapcsgrid"), QLatin1String("0")); m_bUseSnapComponentSizeToGrid = (bool)snapcsgrid.toInt(); QString snapx = qElement.attribute(QLatin1String("snapx"), QLatin1String("10")); QString snapy = qElement.attribute(QLatin1String("snapy"), QLatin1String("10")); m_layoutGrid->setGridSpacing(snapx.toInt(), snapy.toInt()); QString zoom = qElement.attribute(QLatin1String("zoom"), QLatin1String("100")); activeView()->setZoom(zoom.toInt()); resizeSceneToItems(); QString isOpen = qElement.attribute(QLatin1String("isopen"), QLatin1String("1")); m_isOpen = (bool)isOpen.toInt(); int nType = type.toInt(); if (nType == -1 || nType >= 400) { // Pre 1.5.5 numeric values // Values of "type" were changed in 1.5.5 to merge with Settings::Diagram switch (nType) { case 400: m_Type = Uml::DiagramType::UseCase; break; case 401: m_Type = Uml::DiagramType::Collaboration; break; case 402: m_Type = Uml::DiagramType::Class; break; case 403: m_Type = Uml::DiagramType::Sequence; break; case 404: m_Type = Uml::DiagramType::State; break; case 405: m_Type = Uml::DiagramType::Activity; break; case 406: m_Type = Uml::DiagramType::Component; break; case 407: m_Type = Uml::DiagramType::Deployment; break; case 408: m_Type = Uml::DiagramType::EntityRelationship; break; case 409: m_Type = Uml::DiagramType::Object; break; default: m_Type = Uml::DiagramType::Undefined; break; } } else { m_Type = Uml::DiagramType::fromInt(nType); } m_nLocalID = Uml::ID::fromString(localid); if (m_Type == Uml::DiagramType::Sequence || m_Type == Uml::DiagramType::Collaboration) { QString autoIncrementSequence = qElement.attribute(QLatin1String("autoincrementsequence"), QLatin1String("0")); m_autoIncrementSequence = (bool)autoIncrementSequence.toInt(); } QDomNode node = qElement.firstChild(); bool widgetsLoaded = false, messagesLoaded = false, associationsLoaded = false; while (!node.isNull()) { QDomElement element = node.toElement(); if (!element.isNull()) { if (element.tagName() == QLatin1String("widgets")) widgetsLoaded = loadWidgetsFromXMI(element); else if (element.tagName() == QLatin1String("messages")) messagesLoaded = loadMessagesFromXMI(element); else if (element.tagName() == QLatin1String("associations")) associationsLoaded = loadAssociationsFromXMI(element); } node = node.nextSibling(); } if (!widgetsLoaded) { uWarning() << "failed UMLScene load on widgets"; return false; } if (!messagesLoaded) { uWarning() << "failed UMLScene load on messages"; return false; } if (!associationsLoaded) { uWarning() << "failed UMLScene load on associations"; return false; } if (this->type() == Uml::DiagramType::Component) { m_d->addMissingPorts(); m_d->fixPortPositions(); } m_d->removeDuplicatedFloatingTextInstances(); return true; } bool UMLScene::loadWidgetsFromXMI(QDomElement & qElement) { UMLWidget* widget = 0; QDomNode node = qElement.firstChild(); QDomElement widgetElement = node.toElement(); while (!widgetElement.isNull()) { widget = loadWidgetFromXMI(widgetElement); if (widget) { addWidgetCmd(widget); widget->clipSize(); // In the interest of best-effort loading, in case of a // (widget == 0) we still go on. // The individual widget's loadFromXMI1 method should // already have generated an error message to tell the // user that something went wrong. } node = widgetElement.nextSibling(); widgetElement = node.toElement(); } return true; } /** * Loads a "widget" element from XMI, used by loadFromXMI1() and the clipboard. */ UMLWidget* UMLScene::loadWidgetFromXMI(QDomElement& widgetElement) { if (!m_doc) { uWarning() << "m_doc is NULL"; return 0L; } QString tag = widgetElement.tagName(); QString idstr = widgetElement.attribute(QLatin1String("xmi.id"), QLatin1String("-1")); UMLWidget* widget = Widget_Factory::makeWidgetFromXMI(tag, idstr, this); if (widget == 0) return 0; if (!widget->loadFromXMI1(widgetElement)) { widget->cleanup(); delete widget; return 0; } return widget; } bool UMLScene::loadMessagesFromXMI(QDomElement & qElement) { MessageWidget * message = 0; QDomNode node = qElement.firstChild(); QDomElement messageElement = node.toElement(); while (!messageElement.isNull()) { QString tag = messageElement.tagName(); DEBUG(DBG_SRC) << "tag = " << tag; if (tag == QLatin1String("messagewidget") || tag == QLatin1String("UML:MessageWidget")) { // for bkwd compatibility message = new MessageWidget(this, SequenceMessage::Asynchronous, Uml::ID::Reserved); if (!message->loadFromXMI1(messageElement)) { delete message; return false; } addWidgetCmd(message); FloatingTextWidget *ft = message->floatingTextWidget(); if (!ft && message->sequenceMessageType() != SequenceMessage::Creation) DEBUG(DBG_SRC) << "floating text is NULL for message " << Uml::ID::toString(message->id()); } node = messageElement.nextSibling(); messageElement = node.toElement(); } return true; } bool UMLScene::loadAssociationsFromXMI(QDomElement & qElement) { QDomNode node = qElement.firstChild(); QDomElement assocElement = node.toElement(); int countr = 0; while (!assocElement.isNull()) { QString tag = assocElement.tagName(); if (tag == QLatin1String("assocwidget") || tag == QLatin1String("UML:AssocWidget")) { // for bkwd compatibility countr++; AssociationWidget *assoc = AssociationWidget::create(this); if (!assoc->loadFromXMI1(assocElement)) { uError() << "could not loadFromXMI1 association widget:" << assoc << ", bad XMI file? Deleting from UMLScene."; delete assoc; /* return false; Returning false here is a little harsh when the rest of the diagram might load okay. */ } else { assoc->clipSize(); if (!addAssociation(assoc, false)) { uError() << "Could not addAssociation(" << assoc << ") to UMLScene, deleting."; delete assoc; //return false; // soften error.. may not be that bad } } } node = assocElement.nextSibling(); assocElement = node.toElement(); } return true; } /** * Add an object to the application, and update the view. */ void UMLScene::addObject(UMLObject *object) { m_bCreateObject = true; if (m_doc->addUMLObject(object)) m_doc->signalUMLObjectCreated(object); // m_bCreateObject is reset by slotObjectCreated() else m_bCreateObject = false; } bool UMLScene::loadUisDiagramPresentation(QDomElement & qElement) { for (QDomNode node = qElement.firstChild(); !node.isNull(); node = node.nextSibling()) { QDomElement elem = node.toElement(); QString tag = elem.tagName(); if (! UMLDoc::tagEq(tag, QLatin1String("Presentation"))) { uError() << "ignoring unknown UisDiagramPresentation tag " << tag; continue; } QDomNode n = elem.firstChild(); QDomElement e = n.toElement(); QString idStr; int x = 0, y = 0, w = 0, h = 0; while (!e.isNull()) { tag = e.tagName(); DEBUG(DBG_SRC) << "Presentation: tag = " << tag; if (UMLDoc::tagEq(tag, QLatin1String("Presentation.geometry"))) { QDomNode gnode = e.firstChild(); QDomElement gelem = gnode.toElement(); QString csv = gelem.text(); QStringList dim = csv.split(QLatin1Char(',')); x = dim[0].toInt(); y = dim[1].toInt(); w = dim[2].toInt(); h = dim[3].toInt(); } else if (UMLDoc::tagEq(tag, QLatin1String("Presentation.style"))) { // TBD } else if (UMLDoc::tagEq(tag, QLatin1String("Presentation.model"))) { QDomNode mnode = e.firstChild(); QDomElement melem = mnode.toElement(); idStr = melem.attribute(QLatin1String("xmi.idref")); } else { DEBUG(DBG_SRC) << "ignoring tag " << tag; } n = n.nextSibling(); e = n.toElement(); } Uml::ID::Type id = Uml::ID::fromString(idStr); UMLObject *o = m_doc->findObjectById(id); if (o == 0) { uError() << "Cannot find object for id " << idStr; } else { UMLObject::ObjectType ot = o->baseType(); DEBUG(DBG_SRC) << "Create widget for model object of type " << UMLObject::toString(ot); UMLWidget *widget = 0; switch (ot) { case UMLObject::ot_Class: widget = new ClassifierWidget(this, o->asUMLClassifier()); break; case UMLObject::ot_Association: { UMLAssociation *umla = o->asUMLAssociation(); Uml::AssociationType::Enum at = umla->getAssocType(); UMLObject* objA = umla->getObject(Uml::RoleType::A); UMLObject* objB = umla->getObject(Uml::RoleType::B); if (objA == 0 || objB == 0) { uError() << "intern err 1"; return false; } UMLWidget *wA = findWidget(objA->id()); UMLWidget *wB = findWidget(objB->id()); if (wA != 0 && wB != 0) { AssociationWidget *aw = AssociationWidget::create(this, wA, at, wB, umla); aw->syncToModel(); addWidgetCmd(aw); } else { uError() << "cannot create assocwidget from (" ; //<< wA << ", " << wB << ")"; } break; } case UMLObject::ot_Role: { //UMLRole *robj = o->asUMLRole(); //UMLAssociation *umla = robj->getParentAssociation(); // @todo properly display role names. // For now, in order to get the role names displayed // simply delete the participating diagram objects // and drag them from the list view to the diagram. break; } default: uError() << "Cannot create widget of type " << ot; } if (widget) { DEBUG(DBG_SRC) << "Widget: x=" << x << ", y=" << y << ", w=" << w << ", h=" << h; widget->setX(x); widget->setY(y); widget->setSize(w, h); addWidgetCmd(widget); } } } return true; } /** * Loads the "UISDiagram" tag of Unisys.IntegratePlus.2 generated files. */ bool UMLScene::loadUISDiagram(QDomElement & qElement) { QString idStr = qElement.attribute(QLatin1String("xmi.id")); if (idStr.isEmpty()) return false; m_nID = Uml::ID::fromString(idStr); UMLListViewItem *ulvi = 0; for (QDomNode node = qElement.firstChild(); !node.isNull(); node = node.nextSibling()) { if (node.isComment()) continue; QDomElement elem = node.toElement(); QString tag = elem.tagName(); if (tag == QLatin1String("uisDiagramName")) { setName(elem.text()); if (ulvi) ulvi->setText(name()); } else if (tag == QLatin1String("uisDiagramStyle")) { QString diagramStyle = elem.text(); if (diagramStyle != QLatin1String("ClassDiagram")) { uError() << "diagram style " << diagramStyle << " is not yet implemented"; continue; } m_doc->setMainViewID(m_nID); m_Type = Uml::DiagramType::Class; UMLListView *lv = UMLApp::app()->listView(); ulvi = new UMLListViewItem(lv->theLogicalView(), name(), UMLListViewItem::lvt_Class_Diagram, m_nID); } else if (tag == QLatin1String("uisDiagramPresentation")) { loadUisDiagramPresentation(elem); } else if (tag != QLatin1String("uisToolName")) { DEBUG(DBG_SRC) << "ignoring tag " << tag; } } return true; } /** * Left Alignment */ void UMLScene::alignLeft() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal smallestX = WidgetList_Utils::getSmallestX(widgetList); foreach(UMLWidget *widget, widgetList) { widget->setX(smallestX); widget->adjustAssocs(widget->x(), widget->y()); } //TODO: Push stored cmds to stack. } /** * Right Alignment */ void UMLScene::alignRight() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal biggestX = WidgetList_Utils::getBiggestX(widgetList); foreach(UMLWidget *widget, widgetList) { widget->setX(biggestX - widget->width()); widget->adjustAssocs(widget->x(), widget->y()); } //TODO: Push stored cmds to stack. } /** * Top Alignment */ void UMLScene::alignTop() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal smallestY = WidgetList_Utils::getSmallestY(widgetList); foreach(UMLWidget *widget, widgetList) { widget->setY(smallestY); widget->adjustAssocs(widget->x(), widget->y()); } //TODO: Push stored cmds to stack. } /** * Bottom Alignment */ void UMLScene::alignBottom() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal biggestY = WidgetList_Utils::getBiggestY(widgetList); foreach(UMLWidget *widget, widgetList) { widget->setY(biggestY - widget->height()); widget->adjustAssocs(widget->x(), widget->y()); } //TODO: Push stored cmds to stack. } /** * Vertical Middle Alignment */ void UMLScene::alignVerticalMiddle() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal smallestY = WidgetList_Utils::getSmallestY(widgetList); qreal biggestY = WidgetList_Utils::getBiggestY(widgetList); qreal middle = int((biggestY - smallestY) / 2) + smallestY; foreach(UMLWidget *widget, widgetList) { widget->setY(middle - widget->height() / 2); widget->adjustAssocs(widget->x(), widget->y()); } AssociationWidgetList assocList = selectedAssocs(); if (!assocList.isEmpty()) { foreach (AssociationWidget *widget, assocList) { widget->setYEntireAssoc(middle); } } //TODO: Push stored cmds to stack. } /** * Horizontal Middle Alignment */ void UMLScene::alignHorizontalMiddle() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal smallestX = WidgetList_Utils::getSmallestX(widgetList); qreal biggestX = WidgetList_Utils::getBiggestX(widgetList); qreal middle = int((biggestX - smallestX) / 2) + smallestX; foreach(UMLWidget *widget, widgetList) { widget->setX(middle - widget->width() / 2); widget->adjustAssocs(widget->x(), widget->y()); } AssociationWidgetList assocList = selectedAssocs(); if (!assocList.isEmpty()) { foreach (AssociationWidget *widget, assocList) { widget->setXEntireAssoc(middle); } } //TODO: Push stored cmds to stack. } /** * Vertical Distribute Alignment */ void UMLScene::alignVerticalDistribute() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal smallestY = WidgetList_Utils::getSmallestY(widgetList); qreal biggestY = WidgetList_Utils::getBiggestY(widgetList); qreal heightsSum = WidgetList_Utils::getHeightsSum(widgetList); qreal distance = int(((biggestY - smallestY) - heightsSum) / (widgetList.count() - 1.0) + 0.5); qSort(widgetList.begin(), widgetList.end(), Widget_Utils::hasSmallerY); int i = 1; UMLWidget* widgetPrev = 0; foreach(UMLWidget *widget, widgetList) { if (i == 1) { widgetPrev = widget; } else { widget->setY(widgetPrev->y() + widgetPrev->height() + distance); widget->adjustAssocs(widget->x(), widget->y()); widgetPrev = widget; } i++; } //TODO: Push stored cmds to stack. } /** * Horizontal Distribute Alignment */ void UMLScene::alignHorizontalDistribute() { UMLWidgetList widgetList = selectedWidgetsExt(); if (widgetList.isEmpty()) return; qreal smallestX = WidgetList_Utils::getSmallestX(widgetList); qreal biggestX = WidgetList_Utils::getBiggestX(widgetList); qreal widthsSum = WidgetList_Utils::getWidthsSum(widgetList); qreal distance = int(((biggestX - smallestX) - widthsSum) / (widgetList.count() - 1.0) + 0.5); qSort(widgetList.begin(), widgetList.end(), Widget_Utils::hasSmallerX); int i = 1; UMLWidget* widgetPrev = 0; foreach(UMLWidget *widget, widgetList) { if (i == 1) { widgetPrev = widget; } else { widget->setX(widgetPrev->x() + widgetPrev->width() + distance); widget->adjustAssocs(widget->x(), widget->y()); widgetPrev = widget; } i++; } //TODO: Push stored cmds to stack. } /** * Overloading operator for debugging output. */ QDebug operator<<(QDebug dbg, UMLScene *item) { dbg.nospace() << "UMLScene: " << item->name() << " / type=" << DiagramType::toString(item->type()) << " / id=" << Uml::ID::toString(item->ID()) << " / isOpen=" << item->isOpen(); return dbg.space(); } diff --git a/umbrello/umlwidgets/interfacewidget.cpp b/umbrello/umlwidgets/interfacewidget.cpp new file mode 100644 index 000000000..b2656af28 --- /dev/null +++ b/umbrello/umlwidgets/interfacewidget.cpp @@ -0,0 +1,23 @@ +/*************************************************************************** + * 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) 2019 * + * Umbrello UML Modeller Authors * + ***************************************************************************/ + +#include "interfacewidget.h" + +InterfaceWidget::InterfaceWidget(UMLScene *scene, UMLClassifier *c) + : ClassifierWidget(scene, c) +{ + +} + +InterfaceWidget::InterfaceWidget(UMLScene *scene, UMLPackage *p) + : ClassifierWidget(scene, p) +{ + +} diff --git a/umbrello/umlwidgets/interfacewidget.h b/umbrello/umlwidgets/interfacewidget.h new file mode 100644 index 000000000..1466e4918 --- /dev/null +++ b/umbrello/umlwidgets/interfacewidget.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * 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) 2019 * + * Umbrello UML Modeller Authors * + ***************************************************************************/ + +#ifndef INTERFACEWIDGET_H +#define INTERFACEWIDGET_H + +#include "classifierwidget.h" + +/** + * Provides an interface widget + * + * The implementation is currently in @ref ClassifierWidget + * and should be moved to this class for easier implementation + * + * @author Ralf Habacker + */ +class InterfaceWidget : public ClassifierWidget +{ +public: + InterfaceWidget(UMLScene * scene, UMLClassifier * c); + InterfaceWidget(UMLScene * scene, UMLPackage * p); +}; + +#endif // INTERFACEWIDGET_H diff --git a/umbrello/umlwidgets/widget_factory.cpp b/umbrello/umlwidgets/widget_factory.cpp index 7f43a8b41..f1c8f7038 100644 --- a/umbrello/umlwidgets/widget_factory.cpp +++ b/umbrello/umlwidgets/widget_factory.cpp @@ -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) 2006-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ // own header #include "widget_factory.h" // app includes #include "activitywidget.h" #include "actor.h" #include "actorwidget.h" #include "artifact.h" #include "artifactwidget.h" #include "associationwidget.h" #include "boxwidget.h" #include "category.h" #include "categorywidget.h" #include "classifier.h" #include "classifierwidget.h" #include "cmds.h" #include "combinedfragmentwidget.h" #include "component.h" #include "componentwidget.h" #include "datatypewidget.h" #include "debug_utils.h" #include "entity.h" #include "entitywidget.h" #include "enum.h" #include "enumwidget.h" #include "instance.h" #include "floatingdashlinewidget.h" #include "floatingtextwidget.h" #include "folder.h" #include "forkjoinwidget.h" +#include "interfacewidget.h" #include "messagewidget.h" #include "node.h" #include "nodewidget.h" #include "notewidget.h" #include "object_factory.h" #include "objectnodewidget.h" #include "objectwidget.h" #include "package.h" #include "packagewidget.h" #include "pinwidget.h" #include "port.h" #include "portwidget.h" #include "preconditionwidget.h" #include "regionwidget.h" #include "signalwidget.h" #include "statewidget.h" #include "uml.h" #include "umldoc.h" #include "umlscene.h" #include "umlview.h" #include "usecase.h" #include "usecasewidget.h" namespace Widget_Factory { /** * Create a UMLWidget in the given view and representing the given document object. */ UMLWidget *createWidget(UMLScene *scene, UMLObject *o) { QPointF pos = scene->pos(); int y = pos.y(); Uml::DiagramType::Enum diagramType = scene->type(); UMLObject::ObjectType type = o->baseType(); UMLWidget *newWidget = 0; switch (type) { case UMLObject::ot_Actor: if (diagramType == Uml::DiagramType::Sequence) { ObjectWidget *ow = new ObjectWidget(scene, o); ow->setDrawAsActor(true); y = ow->topMargin(); newWidget = ow; } else newWidget = new ActorWidget(scene, o->asUMLActor()); break; case UMLObject::ot_UseCase: newWidget = new UseCaseWidget(scene, o->asUMLUseCase()); break; case UMLObject::ot_Folder: newWidget = new PackageWidget(scene, o->asUMLPackage()); break; case UMLObject::ot_Package: newWidget = new ClassifierWidget(scene, o->asUMLPackage()); break; case UMLObject::ot_Component: newWidget = new ComponentWidget(scene, o->asUMLComponent()); if (diagramType == Uml::DiagramType::Deployment) { newWidget->setIsInstance(true); } break; case UMLObject::ot_Port: { newWidget = new PortWidget(scene, o->asUMLPort()); } break; case UMLObject::ot_Node: newWidget = new NodeWidget(scene, o->asUMLNode()); break; case UMLObject::ot_Artifact: newWidget = new ArtifactWidget(scene, o->asUMLArtifact()); break; case UMLObject::ot_Datatype: newWidget = new DatatypeWidget(scene, o->asUMLClassifier()); break; case UMLObject::ot_Enum: newWidget = new EnumWidget(scene, o->asUMLEnum()); break; case UMLObject::ot_Entity: newWidget = new EntityWidget(scene, o->asUMLEntity()); break; case UMLObject::ot_Interface: if (diagramType == Uml::DiagramType::Sequence || diagramType == Uml::DiagramType::Collaboration) { ObjectWidget *ow = new ObjectWidget(scene, o); if (diagramType == Uml::DiagramType::Sequence) { y = ow->topMargin(); } newWidget = ow; } else { UMLClassifier *c = o->asUMLClassifier(); - ClassifierWidget* interfaceWidget = new ClassifierWidget(scene, c); + InterfaceWidget* interfaceWidget = new InterfaceWidget(scene, c); if (diagramType == Uml::DiagramType::Component || diagramType == Uml::DiagramType::Deployment) { interfaceWidget->setDrawAsCircle(true); } newWidget = interfaceWidget; } break; case UMLObject::ot_Class: if (diagramType == Uml::DiagramType::Object) break; //see if we really want an object widget or class widget if (diagramType == Uml::DiagramType::Class || diagramType == Uml::DiagramType::Component) { UMLClassifier *c = o->asUMLClassifier(); ClassifierWidget *cw = new ClassifierWidget(scene, c); if (diagramType == Uml::DiagramType::Component) cw->setDrawAsCircle(true); newWidget = cw; } else { ObjectWidget *ow = new ObjectWidget(scene, o); if (diagramType == Uml::DiagramType::Sequence) { y = ow->topMargin(); } newWidget = ow; } break; case UMLObject::ot_Instance: newWidget = new ClassifierWidget(scene, o->asUMLInstance()); break; case UMLObject::ot_Category: newWidget = new CategoryWidget(scene, o->asUMLCategory()); break; default: uWarning() << "trying to create an invalid widget (" << UMLObject::toString(type) << ")"; } if (newWidget) { uDebug() << "Widget_Factory::createWidget(" << newWidget->baseType() << ")"; if (newWidget->baseType() != WidgetBase::wt_Pin && newWidget->baseType() != WidgetBase::wt_Port) { newWidget->setX(pos.x()); newWidget->setY(y); } } return newWidget; } bool validateObjType(UMLObject::ObjectType expected, UMLObject* &o, Uml::ID::Type id) { if (o == 0) { uDebug() << "Widget_Factory::validateObjType: creating new object of type " << expected; QString artificialName = QLatin1String("LOST_") + Uml::ID::toString(id); o = Object_Factory::createUMLObject(expected, artificialName, 0, false); if (o == 0) return false; o->setID(id); UMLPackage *parentPkg = o->umlPackage(); parentPkg->addObject(o); return true; } UMLObject::ObjectType actual = o->baseType(); if (actual == expected) return true; uError() << "validateObjType(" << o->name() << "): expected type " << UMLObject::toString(expected) << ", actual type " << UMLObject::toString(actual); return false; } /** * Create a UMLWidget according to the given XMI tag. */ UMLWidget* makeWidgetFromXMI(const QString& tag, const QString& idStr, UMLScene *scene) { UMLWidget *widget = 0; // Loading of widgets which do NOT represent any UMLObject, // just graphic stuff with no real model information //FIXME while boxes and texts are just diagram objects, activities and // states should be UMLObjects if (tag == QLatin1String("statewidget") || tag == QLatin1String("UML:StateWidget")) { widget = new StateWidget(scene, StateWidget::Normal, Uml::ID::Reserved); } else if (tag == QLatin1String("notewidget") || tag == QLatin1String("UML:NoteWidget")) { widget = new NoteWidget(scene, NoteWidget::Normal, Uml::ID::Reserved); } else if (tag == QLatin1String("boxwidget")) { widget = new BoxWidget(scene, Uml::ID::Reserved); } else if (tag == QLatin1String("floatingtext") || tag == QLatin1String("UML:FloatingTextWidget")) { widget = new FloatingTextWidget(scene, Uml::TextRole::Floating, QString(), Uml::ID::Reserved); } else if (tag == QLatin1String("activitywidget") || tag == QLatin1String("UML:ActivityWidget")) { widget = new ActivityWidget(scene, ActivityWidget::Initial, Uml::ID::Reserved); } else if (tag == QLatin1String("messagewidget")) { widget = new MessageWidget(scene, Uml::SequenceMessage::Asynchronous, Uml::ID::Reserved); } else if (tag == QLatin1String("forkjoin")) { widget = new ForkJoinWidget(scene, Qt::Vertical, Uml::ID::Reserved); } else if (tag == QLatin1String("preconditionwidget")) { widget = new PreconditionWidget(scene, 0, Uml::ID::Reserved); } else if (tag == QLatin1String("combinedFragmentwidget")) { widget = new CombinedFragmentWidget(scene, CombinedFragmentWidget::Ref, Uml::ID::Reserved); } else if (tag == QLatin1String("signalwidget")) { widget = new SignalWidget(scene, SignalWidget::Send, Uml::ID::Reserved); } else if (tag == QLatin1String("floatingdashlinewidget")) { widget = new FloatingDashLineWidget(scene, Uml::ID::Reserved); } else if (tag == QLatin1String("objectnodewidget")) { widget = new ObjectNodeWidget(scene, ObjectNodeWidget::Normal, Uml::ID::Reserved); } else if (tag == QLatin1String("regionwidget")) { widget = new RegionWidget(scene, Uml::ID::Reserved); } else if (tag == QLatin1String("pinwidget")) { widget = new PinWidget(scene, 0, Uml::ID::Reserved); } else { // Loading of widgets which represent an UMLObject // Find the UMLObject and create the Widget to represent it Uml::ID::Type id = Uml::ID::fromString(idStr); UMLDoc *umldoc = UMLApp::app()->document(); UMLObject *o = umldoc->findObjectById(id); if (o == 0) { uDebug() << "makeWidgetFromXMI: cannot find object with id " << Uml::ID::toString(id); } if (tag == QLatin1String("actorwidget") || tag == QLatin1String("UML:ActorWidget")) { if (validateObjType(UMLObject::ot_Actor, o, id)) widget = new ActorWidget(scene, o->asUMLActor()); } else if (tag == QLatin1String("usecasewidget") || tag == QLatin1String("UML:UseCaseWidget")) { if (validateObjType(UMLObject::ot_UseCase, o, id)) widget = new UseCaseWidget(scene, o->asUMLUseCase()); } else if (tag == QLatin1String("classwidget") || tag == QLatin1String("UML:ClassWidget") || tag == QLatin1String("UML:ConceptWidget")) { if (validateObjType(UMLObject::ot_Class, o, id) || validateObjType(UMLObject::ot_Package, o, id)) widget = new ClassifierWidget(scene, o->asUMLClassifier()); } else if (tag == QLatin1String("packagewidget")) { if (validateObjType(UMLObject::ot_Package, o, id)) widget = new ClassifierWidget(scene, o->asUMLPackage()); } else if (tag == QLatin1String("componentwidget")) { if (validateObjType(UMLObject::ot_Component, o, id)) widget = new ComponentWidget(scene, o->asUMLComponent()); } else if (tag == QLatin1String("portwidget")) { if (validateObjType(UMLObject::ot_Port, o, id)) widget = new PortWidget(scene, o->asUMLPort()); } else if (tag == QLatin1String("nodewidget")) { if (validateObjType(UMLObject::ot_Node, o, id)) widget = new NodeWidget(scene, o->asUMLNode()); } else if (tag == QLatin1String("artifactwidget")) { if (validateObjType(UMLObject::ot_Artifact, o, id)) widget = new ArtifactWidget(scene, o->asUMLArtifact()); } else if (tag == QLatin1String("interfacewidget")) { if (validateObjType(UMLObject::ot_Interface, o, id)) - widget = new ClassifierWidget(scene, o->asUMLClassifier()); + widget = new InterfaceWidget(scene, o->asUMLClassifier()); } else if (tag == QLatin1String("datatypewidget")) { if (validateObjType(UMLObject::ot_Datatype, o, id)) widget = new DatatypeWidget(scene, o->asUMLClassifier()); } else if (tag == QLatin1String("enumwidget")) { if (validateObjType(UMLObject::ot_Enum, o, id)) widget = new EnumWidget(scene, o->asUMLEnum()); } else if (tag == QLatin1String("entitywidget")) { if (validateObjType(UMLObject::ot_Entity, o, id)) widget = new EntityWidget(scene, o->asUMLEntity()); } else if (tag == QLatin1String("categorywidget")) { if (validateObjType(UMLObject::ot_Category, o, id)) widget = new CategoryWidget(scene, o->asUMLCategory()); } else if (tag == QLatin1String("objectwidget") || tag == QLatin1String("UML:ObjectWidget")) { widget = new ObjectWidget(scene, o); } else if(tag == QLatin1String("instancewidget") || tag == QLatin1String("UML:InstanceWidget")) { if (validateObjType(UMLObject::ot_Instance, o, id)) widget = new ClassifierWidget(scene, o->asUMLInstance()); } else { uWarning() << "Trying to create an unknown widget:" << tag; } } return widget; } } // end namespace Widget_Factory diff --git a/umbrello/umlwidgets/widgetbase.cpp b/umbrello/umlwidgets/widgetbase.cpp index 2046b42df..f3edab3b5 100644 --- a/umbrello/umlwidgets/widgetbase.cpp +++ b/umbrello/umlwidgets/widgetbase.cpp @@ -1,1348 +1,1348 @@ /*************************************************************************** * 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) 2004-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ #include "widgetbase.h" #include "classifier.h" #include "debug_utils.h" #include "dialog_utils.h" #include "floatingtextwidget.h" #include "uml.h" #include "umldoc.h" #include "umllistview.h" #include "umlobject.h" #include "umlscene.h" #include "widgetbasepopupmenu.h" #if QT_VERSION < 0x050000 #include #include #endif #include #include #if QT_VERSION >= 0x050000 #include #include #endif #include /** * Creates a WidgetBase object. * * @param scene The view to be displayed on. * @param type The WidgetType to construct. This must be set to the appropriate * value by the constructors of inheriting classes. */ WidgetBase::WidgetBase(UMLScene *scene, WidgetType type) : QGraphicsObject(), m_baseType(type), m_scene(scene), m_umlObject(0), m_textColor(QColor("black")), m_fillColor(QColor("yellow")), m_brush(m_fillColor), m_lineWidth(0), // initialize with 0 to have valid start condition m_useFillColor(true), m_usesDiagramFillColor(true), m_usesDiagramLineColor(true), m_usesDiagramLineWidth(true), m_usesDiagramTextColor(true), m_usesDiagramUseFillColor(true), m_autoResize(true), m_changesShape(false) { Q_ASSERT(m_baseType > wt_Min && m_baseType < wt_Max); // Note: no virtual methods from derived classes available, // this operation need to be finished in derived class constructor. setLineColor(QColor("black")); setSelected(false); // TODO 310283 setFlags(ItemIsSelectable); //setFlags(ItemIsSelectable | ItemIsMovable |ItemSendsGeometryChanges); if (m_scene) { m_usesDiagramLineColor = true; m_usesDiagramLineWidth = true; m_usesDiagramTextColor = true; const Settings::OptionState& optionState = m_scene->optionState(); m_textColor = optionState.uiState.textColor; setLineColor(optionState.uiState.lineColor); setLineWidth(optionState.uiState.lineWidth); m_font = optionState.uiState.font; } else { uError() << "WidgetBase constructor: SERIOUS PROBLEM - m_scene is NULL"; } } /** * Destructor. */ WidgetBase::~WidgetBase() { } /** * Read property of m_baseType. */ WidgetBase::WidgetType WidgetBase::baseType() const { Q_ASSERT(m_baseType > wt_Min && m_baseType < wt_Max); return m_baseType; } /** * Set property m_baseType. Used for types changing their types during runtime. */ void WidgetBase::setBaseType(const WidgetType& baseType) { Q_ASSERT(baseType > wt_Min && baseType < wt_Max); m_baseType = baseType; } /** * @return The type used for rtti as string. */ QLatin1String WidgetBase::baseTypeStr() const { Q_ASSERT(m_baseType > wt_Min && m_baseType < wt_Max); return QLatin1String(ENUM_NAME(WidgetBase, WidgetType, m_baseType)); } /* * Sets the state of whether the widget is selected. * * @param select The state of whether the widget is selected. */ void WidgetBase::setSelected(bool select) { QGraphicsObject::setSelected(select); } /** * Deliver a pointer to the connected UMLView * (needed esp. by event handling of AssociationLine). */ UMLScene* WidgetBase::umlScene() const { return m_scene; } /** * This is shortcut method for UMLApp::app()->document(). * * @return Pointer to the UMLDoc object. */ UMLDoc* WidgetBase::umlDoc() const { return UMLApp::app()->document(); } /** * Returns the @ref UMLObject set to represent. * * @return the UMLObject to represent. */ UMLObject* WidgetBase::umlObject() const { return m_umlObject; } /** * Sets the @ref UMLObject to represent. * * @param obj The object to represent. */ void WidgetBase::setUMLObject(UMLObject *obj) { m_umlObject = obj; } /** * Write property of m_nId. */ void WidgetBase::setID(Uml::ID::Type id) { if (m_umlObject) { if (m_umlObject->id() != Uml::ID::None) uWarning() << "changing old UMLObject " << Uml::ID::toString(m_umlObject->id()) << " to " << Uml::ID::toString(id); m_umlObject->setID(id); } m_nId = id; } /** * Read property of m_nId. */ Uml::ID::Type WidgetBase::id() const { if (m_umlObject) return m_umlObject->id(); return m_nId; } /** * Used by some child classes to get documentation. * * @return The documentation from the UMLObject (if m_umlObject is set.) */ QString WidgetBase::documentation() const { if (m_umlObject) return m_umlObject->doc(); return m_Doc; } /** * Returns state of documentation for the widget. * * @return false if documentation is empty */ bool WidgetBase::hasDocumentation() { if (m_umlObject) return m_umlObject->hasDoc(); return !m_Doc.isEmpty(); } /** * Used by some child classes to set documentation. * * @param doc The documentation to be set in the UMLObject * (if m_umlObject is set.) */ void WidgetBase::setDocumentation(const QString& doc) { if (m_umlObject) m_umlObject->setDoc(doc); else m_Doc = doc; } /** * Gets the name from the corresponding UMLObject if this widget has an * underlying UMLObject; if it does not, then it returns the local * m_Text (notably the case for FloatingTextWidget.) * * @return the currently set name */ QString WidgetBase::name() const { if (m_umlObject) return m_umlObject->name(); return m_Text; } /** * Sets the name in the corresponding UMLObject. * Sets the local m_Text if m_umlObject is NULL. * * @param strName The name to be set. */ void WidgetBase::setName(const QString &strName) { if (m_umlObject) m_umlObject->setName(strName); else m_Text = strName; } /** * Returns text color * * @return currently used text color */ QColor WidgetBase::textColor() const { return m_textColor; } /** * Sets the text color * * @param color the new text color */ void WidgetBase::setTextColor(const QColor &color) { m_textColor = color; m_usesDiagramTextColor = false; } /** * Returns line color * * @return currently used line color */ QColor WidgetBase::lineColor() const { return m_lineColor; } /** * Sets the line color * * @param color The new line color */ void WidgetBase::setLineColor(const QColor &color) { m_lineColor = color; m_usesDiagramLineColor = false; } /** * Returns fill color * * @return currently used fill color */ QColor WidgetBase::fillColor() const { return m_fillColor; } /** * Sets the fill color * * @param color The new fill color */ void WidgetBase::setFillColor(const QColor &color) { m_fillColor = color; m_usesDiagramFillColor = false; } /** * Returns line width * * @return currently used line with */ uint WidgetBase::lineWidth() const { return m_lineWidth; } /** * Sets the line width * * @param width The new line width */ void WidgetBase::setLineWidth(uint width) { m_lineWidth = width; m_usesDiagramLineWidth = false; } /** * Return state of fill color usage * * @return True if fill color is used */ bool WidgetBase::useFillColor() { return m_useFillColor; } /** * Set state if fill color is used * * @param state The state to set */ void WidgetBase::setUseFillColor(bool state) { m_useFillColor = state; m_usesDiagramUseFillColor = false; } /** * Returns state if diagram text color is used * * @return True means diagram text color is used */ bool WidgetBase::usesDiagramTextColor() const { return m_usesDiagramTextColor; } /** * Set state if diagram text color is used * * @param state The state to set */ void WidgetBase::setUsesDiagramTextColor(bool state) { if (m_usesDiagramTextColor == state) { return; } m_usesDiagramTextColor = state; setTextColor(m_textColor); } /** * Returns state of diagram line color is used * * @return True means diagrams line color is used */ bool WidgetBase::usesDiagramLineColor() const { return m_usesDiagramLineColor; } /** * Set state of diagram line color is used * * @param state The state to set */ void WidgetBase::setUsesDiagramLineColor(bool state) { m_usesDiagramLineColor = state; } /** * Returns state of diagram fill color is used * * @return True means diagrams fill color is used */ bool WidgetBase::usesDiagramFillColor() const { return m_usesDiagramFillColor; } /** * Set state if diagram fill color is used * * @param state The state to set */ void WidgetBase::setUsesDiagramFillColor(bool state) { m_usesDiagramFillColor = state; } /** * Returns state of diagram use fill color is used * * @return True means diagrams fill color is used */ bool WidgetBase::usesDiagramUseFillColor() const { return m_usesDiagramUseFillColor; } /** * Set state of diagram use fill color is used * * @param state The state to set */ void WidgetBase::setUsesDiagramUseFillColor(bool state) { m_usesDiagramUseFillColor = state; } /** * Returns state of diagram line width is used * * @return True means diagrams line width is used */ bool WidgetBase::usesDiagramLineWidth() const { return m_usesDiagramLineWidth; } /** * Set state of diagram line width is used * * @param state The state to set */ void WidgetBase::setUsesDiagramLineWidth(bool state) { m_usesDiagramLineWidth = state; } /** * Returns the font used for diaplaying any text. * @return the font */ QFont WidgetBase::font() const { return m_font; } /** * Set the font used to display text inside this widget. */ void WidgetBase::setFont(const QFont& font) { m_font = font; } /** * Return state of auto resize property * @return the auto resize state */ bool WidgetBase::autoResize() { return m_autoResize; } /** * set auto resize state * @param state */ void WidgetBase::setAutoResize(bool state) { m_autoResize = state; } /** * Return changes state property * @return the changes shape state */ bool WidgetBase::changesShape() { return m_changesShape; } /** * set changes shape property * @param state */ void WidgetBase::setChangesShape(bool state) { m_changesShape = state; } /** * A virtual method for the widget to display a property dialog box. * Subclasses should reimplment this appropriately. * In case the user cancels the dialog or there are some requirements * not fulfilled the method returns false; true otherwise. * * @return true - properties has been applyed * @return false - properties has not been applied * */ bool WidgetBase::showPropertiesDialog() { return false; } /** * A virtual method to save the properties of this widget into a * QDomElement i.e xml. * * Subclasses should first create a new dedicated element as the child * of \a qElement parameter passed. Then this base method should be * called to save basic widget properties. * * @param qDoc A QDomDocument object representing the xml document. * @param qElement A QDomElement representing xml element data. */ void WidgetBase::saveToXMI1(QDomDocument& qDoc, QDomElement& qElement) { Q_UNUSED(qDoc) qElement.setAttribute(QLatin1String("textcolor"), m_usesDiagramTextColor ? QLatin1String("none") : m_textColor.name()); if (m_usesDiagramLineColor) { qElement.setAttribute(QLatin1String("linecolor"), QLatin1String("none")); } else { qElement.setAttribute(QLatin1String("linecolor"), m_lineColor.name()); } if (m_usesDiagramLineWidth) { qElement.setAttribute(QLatin1String("linewidth"), QLatin1String("none")); } else { qElement.setAttribute(QLatin1String("linewidth"), m_lineWidth); } qElement.setAttribute(QLatin1String("usefillcolor"), m_useFillColor); // for consistency the following attributes now use american spelling for "color" qElement.setAttribute(QLatin1String("usesdiagramfillcolor"), m_usesDiagramFillColor); qElement.setAttribute(QLatin1String("usesdiagramusefillcolor"), m_usesDiagramUseFillColor); if (m_usesDiagramFillColor) { qElement.setAttribute(QLatin1String("fillcolor"), QLatin1String("none")); } else { qElement.setAttribute(QLatin1String("fillcolor"), m_fillColor.name()); } qElement.setAttribute(QLatin1String("font"), m_font.toString()); qElement.setAttribute(QLatin1String("autoresize"), m_autoResize ? 1 : 0); } /** * A virtual method to load the properties of this widget from a * QDomElement into this widget. * * Subclasses should reimplement this to load addtional properties * required, calling this base method to load the basic properties of * the widget. * * @param qElement A QDomElement which contains xml info for this widget. * * @todo Add support to load older version. */ bool WidgetBase::loadFromXMI1(QDomElement& qElement) { // first load from "linecolour" and then overwrite with the "linecolor" // attribute if that one is present. The "linecolour" name was a "typo" in // earlier versions of Umbrello QString lineColor = qElement.attribute(QLatin1String("linecolour"), QLatin1String("none")); lineColor = qElement.attribute(QLatin1String("linecolor"), lineColor); if (lineColor != QLatin1String("none")) { setLineColor(QColor(lineColor)); m_usesDiagramLineColor = false; } else if (m_baseType != WidgetBase::wt_Box && m_scene != 0) { setLineColor(m_scene->lineColor()); m_usesDiagramLineColor = true; } QString lineWidth = qElement.attribute(QLatin1String("linewidth"), QLatin1String("none")); if (lineWidth != QLatin1String("none")) { setLineWidth(lineWidth.toInt()); m_usesDiagramLineWidth = false; } else if (m_scene) { setLineWidth(m_scene->lineWidth()); m_usesDiagramLineWidth = true; } QString textColor = qElement.attribute(QLatin1String("textcolor"), QLatin1String("none")); if (textColor != QLatin1String("none")) { m_textColor = QColor(textColor); m_usesDiagramTextColor = false; } else if (m_scene) { m_textColor = m_scene->textColor(); m_usesDiagramTextColor = true; } QString usefillcolor = qElement.attribute(QLatin1String("usefillcolor"), QLatin1String("1")); m_useFillColor = (bool)usefillcolor.toInt(); /* For the next three *color attributes, there was a mixup of american and english spelling for "color". So first we need to keep backward compatibility and try to retrieve the *colour attribute. Next we overwrite this value if we find a *color, otherwise the former *colour is kept. */ QString fillColor = qElement.attribute(QLatin1String("fillcolour"), QLatin1String("none")); fillColor = qElement.attribute(QLatin1String("fillcolor"), fillColor); if (fillColor != QLatin1String("none")) { m_fillColor = QColor(fillColor); } QString usesDiagramFillColor = qElement.attribute(QLatin1String("usesdiagramfillcolour"), QLatin1String("1")); usesDiagramFillColor = qElement.attribute(QLatin1String("usesdiagramfillcolor"), usesDiagramFillColor); m_usesDiagramFillColor = (bool)usesDiagramFillColor.toInt(); QString usesDiagramUseFillColor = qElement.attribute(QLatin1String("usesdiagramusefillcolour"), QLatin1String("1")); usesDiagramUseFillColor = qElement.attribute(QLatin1String("usesdiagramusefillcolor"), usesDiagramUseFillColor); m_usesDiagramUseFillColor = (bool)usesDiagramUseFillColor.toInt(); QString font = qElement.attribute(QLatin1String("font")); if (!font.isEmpty()) { QFont newFont; newFont.fromString(font); m_font = newFont; } else { uWarning() << "Using default font " << m_font.toString() << " for widget with xmi.id " << Uml::ID::toString(m_nId); } QString autoResize = qElement.attribute(QLatin1String("autoresize"), QLatin1String("1")); m_autoResize = (bool)autoResize.toInt(); return true; } /** * Assignment operator */ WidgetBase& WidgetBase::operator=(const WidgetBase& other) { m_baseType = other.m_baseType; m_scene = other.m_scene; m_umlObject = other.m_umlObject; m_Doc = other.m_Doc; m_Text = other.m_Text; m_nId = other.m_nId; m_textColor = other.m_textColor; setLineColor(other.lineColor()); m_fillColor = other.m_fillColor; m_brush = other.m_brush; m_font = other.m_font; m_lineWidth = other.m_lineWidth; m_useFillColor = other.m_useFillColor; m_usesDiagramTextColor = other.m_usesDiagramTextColor; m_usesDiagramLineColor = other.m_usesDiagramLineColor; m_usesDiagramFillColor = other.m_usesDiagramFillColor; m_usesDiagramLineWidth = other.m_usesDiagramLineWidth; setSelected(other.isSelected()); return *this; } /** * return drawing rectangle of widget in local coordinates */ QRectF WidgetBase::rect() const { return m_rect; } /** * set widget rectangle in item coordinates */ void WidgetBase::setRect(const QRectF& rect) { if (m_rect == rect) return; prepareGeometryChange(); m_rect = rect; update(); } /** * set widget rectangle in item coordinates */ void WidgetBase::setRect(qreal x, qreal y, qreal width, qreal height) { setRect(QRectF(x, y, width, height)); } /** * @return The bounding rectangle for this widget. * @see setRect */ QRectF WidgetBase::boundingRect() const { int halfWidth = lineWidth()/2; return m_rect.adjusted(-halfWidth, -halfWidth, halfWidth, halfWidth); } /** * Test if point is inside the bounding rectangle of the widget. * Inheriting classes may reimplement this to test possible child widgets. * * @param p Point to be checked. * * @return 'this' if the given point is in the boundaries of the widget; * else NULL. */ UMLWidget* WidgetBase::onWidget(const QPointF &p) { UMLWidget *uw = this->asUMLWidget(); if (uw == 0) return 0; const qreal w = m_rect.width(); const qreal h = m_rect.height(); const qreal left = x(); // don't use m_rect.x() for this, it is always 0 const qreal right = left + w; const qreal top = y(); // don't use m_rect.y() for this, it is always 0 const qreal bottom = top + h; // uDebug() << "p=(" << p.x() << "," << p.y() // << "), x=" << left << ", y=" << top << ", w=" << w << ", h=" << h // << "; right=" << right << ", bottom=" << bottom; if (p.x() < left || p.x() > right || p.y() < top || p.y() > bottom) { // Qt coord.sys. origin in top left corner // uDebug() << "returning NULL"; return 0; } // uDebug() << "returning this"; return uw; } /** * Draws the UMLWidget on the given paint device * * @param painter The painter for the drawing device * @param option Painting related options * @param widget Background widget on which to paint (optional) * */ void WidgetBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(painter); Q_UNUSED(option); Q_UNUSED(widget); } /** * Reimplemented to show appropriate context menu. */ void WidgetBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { event->accept(); uDebug() << "widget = " << name() << " / type = " << baseTypeStr(); UMLScene *scene = umlScene(); // If right-click was done on a widget that was not selected, clear the // current selection and select the new widget. The context menu is shown // with actions for that single widget. // If a keyboard modifier was used, add the widget to the current selection // and show the menu with actions for the whole selection. if (!isSelected()) { Qt::KeyboardModifiers forSelection = (Qt::ControlModifier | Qt::ShiftModifier); if ((event->modifiers() & forSelection) == 0) { scene->clearSelected(); } if (umlObject() != 0) { scene->selectWidget(this->asUMLWidget()); } else { setSelected(true); } } int count = scene->selectedCount(true); // Determine multi state bool multi = (isSelected() && count > 1); WidgetBasePopupMenu popup(0, this, multi, scene->getUniqueSelectionType()); // Disable the "view code" menu for simple code generators if (UMLApp::app()->isSimpleCodeGeneratorActive()) { popup.setActionEnabled(ListPopupMenu::mt_ViewCode, false); } QAction *triggered = popup.exec(event->screenPos()); slotMenuSelection(triggered); } /** * This is usually called synchronously after menu.exec() and \a * trigger's parent is always the ListPopupMenu which can be used to * get the type of action of \a trigger. * * @note Subclasses can reimplement to handle specific actions and * leave the rest to WidgetBase::slotMenuSelection. */ void WidgetBase::slotMenuSelection(QAction *trigger) { if (!trigger) { return; } QColor newColor; const WidgetType wt = m_baseType; // short hand name ListPopupMenu::MenuType sel = ListPopupMenu::typeFromAction(trigger); switch (sel) { case ListPopupMenu::mt_Rename: umlDoc()->renameUMLObject(umlObject()); break; case ListPopupMenu::mt_Properties: if (wt == WidgetBase::wt_Actor || wt == WidgetBase::wt_UseCase || wt == WidgetBase::wt_Package || wt == WidgetBase::wt_Interface || wt == WidgetBase::wt_Datatype || wt == WidgetBase::wt_Node || wt == WidgetBase::wt_Component || wt == WidgetBase::wt_Artifact || wt == WidgetBase::wt_Enum || wt == WidgetBase::wt_Entity || wt == WidgetBase::wt_Port || wt == WidgetBase::wt_Instance || (wt == WidgetBase::wt_Class && umlScene()->type() == Uml::DiagramType::Class)) { showPropertiesDialog(); } else if (wt == WidgetBase::wt_Object) { m_umlObject->showPropertiesDialog(); } else { uWarning() << "making properties dialog for unknown widget type"; } break; case ListPopupMenu::mt_Line_Color: case ListPopupMenu::mt_Line_Color_Selection: #if QT_VERSION >= 0x050000 newColor = QColorDialog::getColor(lineColor()); if (newColor != lineColor()) { #else newColor = lineColor(); if (KColorDialog::getColor(newColor)) { #endif if (sel == ListPopupMenu::mt_Line_Color_Selection) { umlScene()->selectionSetLineColor(newColor); } else { setLineColor(newColor); } setUsesDiagramLineColor(false); umlDoc()->setModified(true); } break; case ListPopupMenu::mt_Fill_Color: case ListPopupMenu::mt_Fill_Color_Selection: #if QT_VERSION >= 0x050000 newColor = QColorDialog::getColor(fillColor()); if (newColor != fillColor()) { #else newColor = fillColor(); if (KColorDialog::getColor(newColor)) { #endif if (sel == ListPopupMenu::mt_Fill_Color_Selection) { umlScene()->selectionSetFillColor(newColor); } else { setFillColor(newColor); } umlDoc()->setModified(true); } break; case ListPopupMenu::mt_Use_Fill_Color: setUseFillColor(!m_useFillColor); break; case ListPopupMenu::mt_Set_Use_Fill_Color_Selection: umlScene()->selectionUseFillColor(true); break; case ListPopupMenu::mt_Unset_Use_Fill_Color_Selection: umlScene()->selectionUseFillColor(false); break; case ListPopupMenu::mt_Show_Attributes_Selection: case ListPopupMenu::mt_Hide_Attributes_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowAttributes, sel != ListPopupMenu::mt_Hide_Attributes_Selection ); break; case ListPopupMenu::mt_Show_Operations_Selection: case ListPopupMenu::mt_Hide_Operations_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowOperations, sel != ListPopupMenu::mt_Hide_Operations_Selection ); break; case ListPopupMenu::mt_Show_Visibility_Selection: case ListPopupMenu::mt_Hide_Visibility_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowVisibility, sel != ListPopupMenu::mt_Hide_Visibility_Selection ); break; case ListPopupMenu::mt_Show_Operation_Signature_Selection: case ListPopupMenu::mt_Hide_Operation_Signature_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowOperationSignature, sel != ListPopupMenu::mt_Hide_Operation_Signature_Selection ); break; case ListPopupMenu::mt_Show_Attribute_Signature_Selection: case ListPopupMenu::mt_Hide_Attribute_Signature_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowAttributeSignature, sel != ListPopupMenu::mt_Hide_Attribute_Signature_Selection ); break; case ListPopupMenu::mt_Show_Packages_Selection: case ListPopupMenu::mt_Hide_Packages_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowPackage, sel != ListPopupMenu::mt_Hide_Packages_Selection ); break; case ListPopupMenu::mt_Show_Stereotypes_Selection: case ListPopupMenu::mt_Hide_Stereotypes_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowStereotype, sel != ListPopupMenu::mt_Hide_Stereotypes_Selection ); break; case ListPopupMenu::mt_Hide_NonPublic_Selection: case ListPopupMenu::mt_Show_NonPublic_Selection: umlScene()->selectionSetVisualProperty( ClassifierWidget::ShowPublicOnly, sel != ListPopupMenu::mt_Show_NonPublic_Selection ); break; case ListPopupMenu::mt_ViewCode: { UMLClassifier *c = umlObject()->asUMLClassifier(); if (c) { UMLApp::app()->viewCodeDocument(c); } break; } case ListPopupMenu::mt_Remove: umlScene()->deleteSelection(); break; case ListPopupMenu::mt_Delete: if (!Dialog_Utils::askDeleteAssociation()) break; umlScene()->deleteSelection(); break; case ListPopupMenu::mt_Change_Font: case ListPopupMenu::mt_Change_Font_Selection: { #if QT_VERSION >= 0x050000 bool ok = false; QFont newFont = QFontDialog::getFont(&ok, font()); if (ok) { #else QFont newFont = font(); if (KFontDialog::getFont(newFont, KFontChooser::NoDisplayFlags, 0) == KFontDialog::Accepted) { #endif if (sel == ListPopupMenu::mt_Change_Font_Selection) { m_scene->selectionSetFont(newFont); } else { setFont(newFont); } } } break; case ListPopupMenu::mt_Cut: umlScene()->setStartedCut(); UMLApp::app()->slotEditCut(); break; case ListPopupMenu::mt_Copy: UMLApp::app()->slotEditCopy(); break; case ListPopupMenu::mt_Paste: UMLApp::app()->slotEditPaste(); break; case ListPopupMenu::mt_Refactoring: //check if we are operating on a classifier, or some other kind of UMLObject if (umlObject()->asUMLClassifier()) { UMLApp::app()->refactor(umlObject()->asUMLClassifier()); } break; case ListPopupMenu::mt_Clone: { foreach (UMLWidget* widget, umlScene()->selectedWidgets()) { if (Model_Utils::isCloneable(widget->baseType())) { UMLObject *clone = widget->umlObject()->clone(); umlScene()->addObject(clone); } } } break; case ListPopupMenu::mt_Rename_MultiA: case ListPopupMenu::mt_Rename_MultiB: case ListPopupMenu::mt_Rename_Name: case ListPopupMenu::mt_Rename_RoleAName: case ListPopupMenu::mt_Rename_RoleBName: { FloatingTextWidget *ft = static_cast(this); ft->handleRename(); break; } case ListPopupMenu::mt_Align_Right: umlScene()->alignRight(); break; case ListPopupMenu::mt_Align_Left: umlScene()->alignLeft(); break; case ListPopupMenu::mt_Align_Top: umlScene()->alignTop(); break; case ListPopupMenu::mt_Align_Bottom: umlScene()->alignBottom(); break; case ListPopupMenu::mt_Align_VerticalMiddle: umlScene()->alignVerticalMiddle(); break; case ListPopupMenu::mt_Align_HorizontalMiddle: umlScene()->alignHorizontalMiddle(); break; case ListPopupMenu::mt_Align_VerticalDistribute: umlScene()->alignVerticalDistribute(); break; case ListPopupMenu::mt_Align_HorizontalDistribute: umlScene()->alignHorizontalDistribute(); break; default: uDebug() << "MenuType " << ListPopupMenu::toString(sel) << " not implemented"; break; } } /** * Helper function for debug output. * Returns the given enum value as string. * @param wt WidgetType of which a string representation is wanted * @return the WidgetType as string */ QString WidgetBase::toString(WidgetType wt) { return QLatin1String(ENUM_NAME(WidgetBase, WidgetType, wt)); } /** * Returns the given enum value as localized string. * @param wt WidgetType of which a string representation is wanted * @return the WidgetType as localized string */ QString WidgetBase::toI18nString(WidgetType wt) { QString name; switch (wt) { case wt_Activity: name = i18n("Activity"); break; case wt_Actor: name = i18n("Actor"); break; case wt_Artifact: name = i18n("Artifact"); break; case wt_Association: name = i18n("Association"); break; case wt_Box: name = i18n("Box"); break; case wt_Category: name = i18n("Category"); break; case wt_CombinedFragment: name = i18n("CombinedFragment"); break; case wt_Component: name = i18n("Component"); break; case wt_Class: name = i18n("Class"); break; case wt_Datatype: name = i18n("Datatype"); break; case wt_Entity: name = i18n("Entity"); break; case wt_Enum: name = i18n("Enum"); break; case wt_FloatingDashLine: name = i18n("FloatingDashLine"); break; case wt_ForkJoin: name = i18n("ForkJoin"); break; case wt_Interface: name = i18n("Interface"); break; case wt_Message: name = i18n("Message"); break; case wt_Node: name = i18n("Node"); break; case wt_Note: name = i18n("Note"); break; case wt_Object: name = i18n("Object"); break; case wt_ObjectNode: name = i18n("ObjectNode"); break; case wt_Package: name = i18n("Package"); break; case wt_Pin: name = i18n("Pin"); break; case wt_Port: name = i18n("Port"); break; case wt_Precondition: name = i18n("Precondition"); break; case wt_Region: name = i18n("Region"); break; case wt_Signal: name = i18n("Signal"); break; case wt_State: name = i18n("State"); break; case wt_Text: name = i18n("Text"); break; case wt_UseCase: name = i18n("UseCase"); break; case wt_Instance: name = i18n("Instance"); break; default: name = QLatin1String(" &name:"); uWarning() << "unknown widget type"; break; } return name; } /** * Returns the given enum value as icon type. * @param wt WidgetType of which an icon type representation is wanted * @return the WidgetType as icon type */ Icon_Utils::IconType WidgetBase::toIcon(WidgetBase::WidgetType wt) { Icon_Utils::IconType icon; switch (wt) { case wt_Activity: icon = Icon_Utils::it_Activity; break; case wt_Actor: icon = Icon_Utils::it_Actor; break; case wt_Artifact: icon = Icon_Utils::it_Artifact; break; case wt_Association: icon = Icon_Utils::it_Association; break; case wt_Box: icon = Icon_Utils::it_Box; break; case wt_Category: icon = Icon_Utils::it_Category; break; case wt_CombinedFragment: icon = Icon_Utils::it_Combined_Fragment; break; case wt_Component: icon = Icon_Utils::it_Component; break; case wt_Class: icon = Icon_Utils::it_Class; break; case wt_Datatype: icon = Icon_Utils::it_Datatype; break; case wt_Entity: icon = Icon_Utils::it_Entity; break; case wt_Enum: icon = Icon_Utils::it_Enum; break; case wt_FloatingDashLine: icon = Icon_Utils::it_Association; break; case wt_ForkJoin: icon = Icon_Utils::it_Fork_Join; break; case wt_Instance: icon = Icon_Utils::it_Instance; break; case wt_Interface: icon = Icon_Utils::it_Interface; break; case wt_Message: icon = Icon_Utils::it_Message_Synchronous; break; case wt_Node: icon = Icon_Utils::it_Node; break; case wt_Note: icon = Icon_Utils::it_Note; break; case wt_Object: icon = Icon_Utils::it_Object; break; case wt_ObjectNode: icon = Icon_Utils::it_Object_Node; break; case wt_Package: icon = Icon_Utils::it_Package; break; case wt_Pin: icon = Icon_Utils::it_Pin; break; case wt_Port: icon = Icon_Utils::it_Port; break; case wt_Precondition: icon = Icon_Utils::it_Precondition; break; case wt_Region: icon = Icon_Utils::it_Region; break; case wt_Signal: icon = Icon_Utils::it_Send_Signal; break; case wt_State: icon = Icon_Utils::it_State; break; case wt_Text: icon = Icon_Utils::it_Text; break; case wt_UseCase: icon = Icon_Utils::it_UseCase; break; default: icon = Icon_Utils::it_Home; uWarning() << "unknown widget type"; break; } return icon; } #include "activitywidget.h" #include "actorwidget.h" #include "artifactwidget.h" #include "associationwidget.h" #include "boxwidget.h" #include "categorywidget.h" //#include "classwidget.h" #include "combinedfragmentwidget.h" #include "componentwidget.h" #include "datatypewidget.h" #include "entitywidget.h" #include "enumwidget.h" #include "floatingdashlinewidget.h" #include "forkjoinwidget.h" -//#include "interfacewidget.h" +#include "interfacewidget.h" #include "messagewidget.h" #include "nodewidget.h" #include "notewidget.h" #include "objectnodewidget.h" #include "objectwidget.h" #include "packagewidget.h" #include "pinwidget.h" #include "portwidget.h" #include "preconditionwidget.h" #include "regionwidget.h" #include "signalwidget.h" #include "statewidget.h" #include "usecasewidget.h" ActivityWidget* WidgetBase::asActivityWidget() { return dynamic_cast(this); } ActorWidget* WidgetBase::asActorWidget() { return dynamic_cast(this); } ArtifactWidget* WidgetBase::asArtifactWidget() { return dynamic_cast(this); } AssociationWidget* WidgetBase::asAssociationWidget() { return dynamic_cast(this); } BoxWidget* WidgetBase::asBoxWidget() { return dynamic_cast(this); } CategoryWidget* WidgetBase::asCategoryWidget() { return dynamic_cast(this); } ClassifierWidget* WidgetBase::asClassifierWidget() { return dynamic_cast(this); } CombinedFragmentWidget* WidgetBase::asCombinedFragmentWidget() { return dynamic_cast(this); } ComponentWidget* WidgetBase::asComponentWidget() { return dynamic_cast(this); } DatatypeWidget* WidgetBase::asDatatypeWidget() { return dynamic_cast(this); } EntityWidget* WidgetBase::asEntityWidget() { return dynamic_cast(this); } EnumWidget* WidgetBase::asEnumWidget() { return dynamic_cast(this); } FloatingDashLineWidget* WidgetBase::asFloatingDashLineWidget() { return dynamic_cast(this); } ForkJoinWidget* WidgetBase::asForkJoinWidget() { return dynamic_cast(this); } -//InterfaceWidget* WidgetBase::asInterfaceWidget() { return dynamic_cast(this); } +InterfaceWidget* WidgetBase::asInterfaceWidget() { return dynamic_cast(this); } MessageWidget* WidgetBase::asMessageWidget() { return dynamic_cast(this); } NodeWidget* WidgetBase::asNodeWidget() { return dynamic_cast(this); } NoteWidget* WidgetBase::asNoteWidget() { return dynamic_cast(this); } ObjectNodeWidget* WidgetBase::asObjectNodeWidget() { return dynamic_cast(this); } ObjectWidget* WidgetBase::asObjectWidget() { return dynamic_cast(this); } PackageWidget* WidgetBase::asPackageWidget() { return dynamic_cast(this); } PinWidget* WidgetBase::asPinWidget() { return dynamic_cast(this); } PinPortBase *WidgetBase::asPinPortBase() { return dynamic_cast(this); } PortWidget* WidgetBase::asPortWidget() { return dynamic_cast(this); } PreconditionWidget* WidgetBase::asPreconditionWidget() { return dynamic_cast(this); } RegionWidget* WidgetBase::asRegionWidget() { return dynamic_cast(this); } SignalWidget* WidgetBase::asSignalWidget() { return dynamic_cast(this); } StateWidget* WidgetBase::asStateWidget() { return dynamic_cast(this); } FloatingTextWidget* WidgetBase::asFloatingTextWidget() { return dynamic_cast(this); } //TextWidget* WidgetBase::asTextWidget() { return dynamic_cast(this); } UseCaseWidget* WidgetBase::asUseCaseWidget() { return dynamic_cast(this); } UMLWidget *WidgetBase::asUMLWidget() { return dynamic_cast(this); } diff --git a/umbrello/umlwidgets/widgetbase.h b/umbrello/umlwidgets/widgetbase.h index 4e27b7906..ce668ba19 100644 --- a/umbrello/umlwidgets/widgetbase.h +++ b/umbrello/umlwidgets/widgetbase.h @@ -1,303 +1,303 @@ /*************************************************************************** * 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) 2004-2014 * * Umbrello UML Modeller Authors * ***************************************************************************/ #ifndef WIDGETBASE_H #define WIDGETBASE_H #include "basictypes.h" #include "icon_utils.h" #include #include #include #include #include #include #include // forward declarations class QAction; class ActivityWidget; class ActorWidget; class ArtifactWidget; class AssociationWidget; class BoxWidget; class CategoryWidget; class ClassifierWidget; class CombinedFragmentWidget; class ComponentWidget; class DatatypeWidget; class EntityWidget; class EnumWidget; class FloatingDashLineWidget; class FloatingTextWidget; class ForkJoinWidget; -//class InterfaceWidget; +class InterfaceWidget; class MessageWidget; class NodeWidget; class NoteWidget; class ObjectNodeWidget; class ObjectWidget; class PackageWidget; class PinWidget; class PortWidget; class PinPortBase; class PreconditionWidget; class RegionWidget; class SignalWidget; class StateWidget; //class TextWidget; class UseCaseWidget; class UMLDoc; class UMLObject; class UMLScene; class UMLWidget; // required by function onWidget() /** * @short Common base class for UMLWidget and AssociationWidget * @author Oliver Kellogg * Bugs and comments to umbrello-devel@kde.org or http://bugs.kde.org */ class WidgetBase : public QGraphicsObject { Q_OBJECT Q_ENUMS(WidgetType) public: enum WidgetType { wt_Min = 299, // lower bounds check value wt_UMLWidget, // does not have UMLObject representation wt_Actor, // has UMLObject representation wt_UseCase, // has UMLObject representation wt_Class, // has UMLObject representation wt_Interface, // has UMLObject representation wt_Datatype, // has UMLObject representation wt_Enum, // has UMLObject representation wt_Entity, // has UMLObject representation wt_Package, // has UMLObject representation wt_Object, // has UMLObject representation wt_Note, // does not have UMLObject representation wt_Box, // does not have UMLObject representation wt_Message, // does not have UMLObject representation wt_Text, // does not have UMLObject representation wt_State, // does not have UMLObject representation wt_Activity, // does not have UMLObject representation wt_Component, // has UMLObject representation wt_Artifact, // has UMLObject representation wt_Node, // has UMLObject representation wt_Association, // has UMLObject representation wt_ForkJoin, // does not have UMLObject representation wt_Precondition, // does not have UMLObject representation wt_CombinedFragment, // does not have UMLObject representation wt_FloatingDashLine, // does not have UMLObject representation wt_Signal, // does not have UMLObject representation wt_Pin, wt_ObjectNode, wt_Region, wt_Category, // has UMLObject representation wt_Port, // has UMLObject representation wt_Instance, // has UMLObject representation == wt_Object wt_Max // upper bounds check value }; static QString toString(WidgetType wt); static QString toI18nString(WidgetType wt); static Icon_Utils::IconType toIcon(WidgetType wt); explicit WidgetBase(UMLScene * scene, WidgetType type= wt_UMLWidget); virtual ~WidgetBase(); UMLObject* umlObject() const; virtual void setUMLObject(UMLObject *obj); Uml::ID::Type id() const; void setID(Uml::ID::Type id); WidgetType baseType() const; void setBaseType(const WidgetType& baseType); QLatin1String baseTypeStr() const; virtual void setSelected(bool select); UMLScene* umlScene() const; UMLDoc* umlDoc() const; QString documentation() const; bool hasDocumentation(); virtual void setDocumentation(const QString& doc); QString name() const; virtual void setName(const QString &strName); QColor lineColor() const; virtual void setLineColor(const QColor& color); uint lineWidth() const; virtual void setLineWidth(uint width); QColor textColor() const; virtual void setTextColor(const QColor& color); QColor fillColor() const; virtual void setFillColor(const QColor& color); bool usesDiagramLineColor() const; void setUsesDiagramLineColor(bool state); bool usesDiagramLineWidth() const; void setUsesDiagramLineWidth(bool state); bool useFillColor(); virtual void setUseFillColor(bool state); bool usesDiagramTextColor() const; void setUsesDiagramTextColor(bool state); bool usesDiagramFillColor() const; void setUsesDiagramFillColor(bool state); bool usesDiagramUseFillColor() const; void setUsesDiagramUseFillColor(bool state); virtual QFont font() const; virtual void setFont(const QFont& font); bool autoResize(); void setAutoResize(bool state); bool changesShape(); void setChangesShape(bool state); virtual bool showPropertiesDialog(); virtual bool loadFromXMI1(QDomElement &qElement); virtual void saveToXMI1(QDomDocument &qDoc, QDomElement &qElement); WidgetBase& operator=(const WidgetBase& other); QRectF rect() const; void setRect(const QRectF& rect); void setRect(qreal x, qreal y, qreal width, qreal height); virtual QRectF boundingRect() const; virtual UMLWidget* onWidget(const QPointF &p); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); bool isActivityWidget() { return baseType() == wt_Activity; } bool isActorWidget() { return baseType() == wt_Actor; } bool isArtifactWidget() { return baseType() == wt_Artifact; } bool isAssociationWidget() { return baseType() == wt_Association; } bool isBoxWidget() { return baseType() == wt_Box; } bool isCategoryWidget() { return baseType() == wt_Category; } bool isClassWidget() { return baseType() == wt_Class; } bool isCombinedFragmentWidget() { return baseType() == wt_CombinedFragment; } bool isComponentWidget() { return baseType() == wt_Component; } bool isDatatypeWidget() { return baseType() == wt_Datatype; } bool isEntityWidget() { return baseType() == wt_Entity; } bool isEnumWidget() { return baseType() == wt_Enum; } bool isFloatingDashLineWidget() { return baseType() == wt_FloatingDashLine; } bool isForkJoinWidget() { return baseType() == wt_ForkJoin; } bool isInterfaceWidget() { return baseType() == wt_Interface; } bool isMessageWidget() { return baseType() == wt_Message; } bool isNodeWidget() { return baseType() == wt_Node; } bool isNoteWidget() { return baseType() == wt_Note; } bool isObjectNodeWidget() { return baseType() == wt_ObjectNode; } bool isObjectWidget() { return baseType() == wt_Object; } bool isPackageWidget() { return baseType() == wt_Package; } bool isPinWidget() { return baseType() == wt_Pin; } bool isPortWidget() { return baseType() == wt_Port; } bool isPreconditionWidget() { return baseType() == wt_Precondition; } bool isRegionWidget() { return baseType() == wt_Region; } bool isSignalWidget() { return baseType() == wt_Signal; } bool isStateWidget() { return baseType() == wt_State; } bool isTextWidget() { return baseType() == wt_Text; } bool isUseCaseWidget() { return baseType() == wt_UseCase; } ActivityWidget* asActivityWidget(); ActorWidget* asActorWidget(); ArtifactWidget* asArtifactWidget(); AssociationWidget* asAssociationWidget(); BoxWidget* asBoxWidget(); CategoryWidget* asCategoryWidget(); ClassifierWidget* asClassifierWidget(); CombinedFragmentWidget* asCombinedFragmentWidget(); ComponentWidget* asComponentWidget(); DatatypeWidget* asDatatypeWidget(); EntityWidget* asEntityWidget(); EnumWidget* asEnumWidget(); FloatingDashLineWidget* asFloatingDashLineWidget(); ForkJoinWidget* asForkJoinWidget(); - //InterfaceWidget* asInterfaceWidget(); + InterfaceWidget* asInterfaceWidget(); MessageWidget* asMessageWidget(); NodeWidget* asNodeWidget(); NoteWidget* asNoteWidget(); ObjectNodeWidget* asObjectNodeWidget(); ObjectWidget* asObjectWidget(); PackageWidget* asPackageWidget(); PinWidget* asPinWidget(); PinPortBase* asPinPortBase(); PortWidget* asPortWidget(); PreconditionWidget* asPreconditionWidget(); RegionWidget* asRegionWidget(); SignalWidget* asSignalWidget(); StateWidget* asStateWidget(); FloatingTextWidget* asFloatingTextWidget(); // TextWidget* asTextWidget(); UseCaseWidget* asUseCaseWidget(); UMLWidget* asUMLWidget(); public Q_SLOTS: virtual void slotMenuSelection(QAction *trigger); protected: virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); private: WidgetType m_baseType; ///< Type of widget. protected: UMLScene *m_scene; QPointer m_umlObject; QString m_Doc; ///< Only used if m_umlObject is not set. QString m_Text; QRectF m_rect; ///< widget size /** * This ID is only used when the widget does not have a * corresponding UMLObject (i.e. the m_umlObject pointer is NULL.) * For UMLObjects, the ID from the UMLObject is used. */ Uml::ID::Type m_nId; QColor m_textColor; ///< Color of the text of the widget. Is saved to XMI. QColor m_lineColor; ///< Color of the lines of the widget. Is saved to XMI. QColor m_fillColor; ///< color of the background of the widget QBrush m_brush; QFont m_font; uint m_lineWidth; ///< Width of the lines of the widget. Is saved to XMI. bool m_useFillColor; ///< flag indicates if the UMLWidget uses the Diagram FillColour /** * true by default, false if the colors have * been explicitly set for this widget. * These are saved to XMI. */ bool m_usesDiagramFillColor; bool m_usesDiagramLineColor; bool m_usesDiagramLineWidth; bool m_usesDiagramTextColor; bool m_usesDiagramUseFillColor; bool m_autoResize; bool m_changesShape; ///< The widget changes its shape when the number of connections or their positions are changed }; #endif